正则表达式分为两类:

    基本正则表达式:BRE

    扩展正则表达式:ERE


基本正则表达式的元字符:

字符匹配:

    .:  匹配任意单个字符;

    []: 匹配指定范围内的任意单个字符

    [^]:匹配指定范围外的任意单个字符

        [:digit:],[:upper:],[:lower:],[:alpha:],[:alnum:],[:space:],[:punct:]

匹配次数用在要指定次数的字符后面,用于指定前面的字符出现的次数

    *:匹配前面的字符任意次;(0次1次或多次)

    例如:grep "x*y"

        abxy

        xay

        xxxxxxxxxy

        贪婪模式

    .*:任意长度的任意字符

    \?:匹配其前面的字符0或1次;即前面的可有可无

    \+:匹配其前面的字符至少1次

    \{m\}:匹配前面的字符m次;

    \{m,n\}:匹配前面的字符至少m次,至多n次

    \{0,n\}:匹配前面的字符至多n次;

    \{m,\}:匹配前面的字符至少m次;

位置锚定:

    ^:行首锚定:用于模式的最左侧;

    $:行尾锚定:用于模式的最右侧;

    ^PATTERN$:用于模式匹配整行;

    ^$:空行;

    ^[[:apace:]]*$:这个空白可以没有,有任意个都算

    \< 或 \b:词首锚定:用于单词模式的左侧;

    \> 或 \b:词尾锚定:用于单词模式的右侧;

    \<PATTERN\>:匹配整个单词;


示例:

[root@C7-1 ~]# grep '\<[[:alpha:]]\{1,3\}t' grep.txt       #锚定单词首部

rootkjkdfierlqkejwlekjwlkroot

[root@C7-1 ~]# grep '[[:alpha:]]\{1,3\}t\>' grep.txt       #锚定单词尾部

rootkjkdfierlqkejwlekjwlkroot

[root@C7-1 ~]# grep '^[[:alpha:]]\{3\}t' /etc/passwd           ^匹配行首

root:x:0:0:root:/root:/bin/bash

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

postfix:x:89:89::/var/spool/postfix:/sbin/nologin

[root@C7-1 ~]# grep '[[:alpha:]]\{3\}t$' /etc/passwd            $匹配行尾

halt:x:7:0:halt:/sbin:/sbin/halt


分组:

    \(\):将一个或多个字符捆绑在一起,当作一个整体进行处理;

        # grep "\(xy\)\+" grep.txt

        \(xy\)*ab

Note:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为:\1,\2,\3,.....

    \1:从左侧起,第一个左括号以及与之匹配右括号之间的模式所匹配到的字符;

        \(ab\+\(xy\)*\):

            \1:ab\+\(xy\)*

            \2:xy

反向引用:引用前面的分组括号中的模式所匹配字符,(而非模式本身)


练习:

1、显示/proc/meminfo文件中以大小S开头的行;(要求:使用两种方式)

# grep -i '^s' /proc/meminfo         #-i忽略大小写,^s以s为开头

# grep '^[Ss]' /proc/meminfo 

2、显示/etc/passwd文件中不以/bin/bash结尾的行;

# grep '/bin/bash$' /etc/passwd          #这一条是取出以/bin/bash结尾的行

# grep -v '/bin/bash$' /etc/passwd       #-v参数是排除包含关键字的行

3、显示/etc/passwd文件中ID号最大的用户的用户名;

# sort -t: -k3 -n /etc/passwd            #-t:指定分隔符,-k3指定字段,-n以数值大小排序

# sort -t: -k3 -n /etc/passwd | tail -1   #上面的命令把最大的排在最后,tail -1显示最后一条数据

# sort -t: -k3 -n /etc/passwd | tail -1 | cut -d: -f1  #-d:指明分隔符,-f1指定字段

4、如果用户root存在,显示其默认的shell程序;

# grep "^root:" /etc/passwd          #单独查找root是否存在命令

# grep "^root\>" /etc/passwd       #词首和词尾锚定

# id root &> /dev/null && grep "^root\>" /etc/passwd | cut -d: -f7     #id查找,如果root存储,就显示root的默认shell

5、找出/etc/passwd中的两位或三位数

# grep "\<[0-9]\{2,3\}\>" /etc/passwd        #如果不使用\<,\>词首词尾锚定,就有可能会匹配4位中的3位。

6、显示/etc/rc.d/rc.sysinit文件中,至少以一个空白字符开头的且后面存非空白字符的行

# grep "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg

7、找出“netstat -tan”命令的结果中以'LISTEN'后跟0、1或多个空白字符结尾的行;

# netstat -tan | grep "LISTEN[[:space:]]*$"      #空格后面的*$表示结尾有多个空格

8、添加用户bash、testbash、basher以及nologin(其shell为/sbin/nologin);而后找出/etc/passwd文件中用户名同shell名的行;

grep "^\([[:alnum:]]\+\>\).*\1$" /etc/passwd    #做分组中间可出现任意内容,结尾匹配行首

练习:

1、写一个脚本,实现如下功能

如果user用户存在,就显示其存在,否则添加之;

显示添加的用户的id号等信息;

#!/bin/bash

id user1 &> /dev/null && echo "user1 exists." || useradd user1

id user1

2、写一个脚本,完成如下功能  

如果root用户登录了当前系统,就显示root用户在线;否则说明其未登录

# w | grep "^root\>" &> /dev/null && echo "root logged" || echo "root not logged"


egrep及扩展的正则表达式 

egrep =  grep -E

egrep [OPTIONS] PATTERN [FILE...]

扩展正则表达式的元字符:

字符匹配:

    .

    []

    [^]

次数匹配:

    *

    ?:0或1次

    +:1次或多次

    {m}:匹配m次

    {m,n]:至少m,至多n次

锚定:

    ^

    $

    \<,\b

    \>,\b

分组:

    ()

    后向引用:\1,\2, ...

或者:

    a|b

    C|cat:C或cat


视频15 36分

练习:

1、显示当前系统root、centos或user1用户的默认shell和UID;

# grep -E '^(root|centos|user)\>' /etc/passwd | cut -d: -f1,3,7    #(root|centos|user)这个属于扩展正则表达式,所以要使用egrep或grep -E

2、找出/etc/rc.d/init.d/functions文件(centos6)中某单词后面跟一个小括号的行(只能在6上)

# grep -E -o "^[_[:alpha:]]+\(\)" /etc/rc.d/init.d/functions

3、使用echo输出一绝对路径,使用egrep取出其基名;(基名就是/etc/passwd passwd就是)

# echo "/mnt/sdc" | grep -E "[^/]+$"                              #行尾的字符串,[^/]除了/斜线的任意内容,+代表这个/至少出现1次

[root@cat ~]# echo "/mnt/sdc/" | grep -E "[^/]+/?$"     #如果sdc后还带一个/,就用/?表示可有可无

[root@cat ~]# echo "/mnt/sdc" | grep -E -o "[^/]+/?$" | cut -d"/" -f1   #以/作为分隔符,取第1字段,来取sdc


/mnt/sdc/

进一步地:使用egrep取出路径的目录名,类似于dirname命令的结果


4、找出ifconfig命令结果中1-255之间的数值;

# ifconfig | grep -E -o "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"

5、找出ifconfig命令结果中的IP地址

# ifconfig eth0 | grep "inet addr" | cut -d: -f 2|cut -d " " -f 1


fgrep:不支持正则表达式搜索;