正则表达式的简单认识

文本搜索工具,根据用户指定的"模式(pattern)"对目标文本进行过滤,显示被模式匹配到的行。

一、什么是正则表达式?

正则表达式:由一类字符书写的模式,其中有些字符不表示字符的字面意义,而是表示控制或通配的功能;

二、正则表达式元字符

正则表达式语言由两种基本字符类型组成:原义(正常)文本字符和元字符。元字符使正则表达式具有处理能力。元字符既可以是放在 [] 中的任意单个字符(如 [a] 表示匹配单个小写字符 a ),也可以是字符序列(如 [a-d] 表示匹配 a 、 b 、 c 、 d 之间的任意一个字符,而 w 表示任意英文字母和数字及下划线),下面是一些常见的元字符:  
.    匹配除 以外的任意单字符(注意元字符是小数点)。 
 
[abcde]  匹配 abcde 之中的任意一个字符 
 
[a-h]   匹配 a 到 h 之间的任意一个字符 
 
[^fgh]  不与 fgh 之中的任意一个字符匹配 
 
 匹配大小写英文字符及数字 0 到 9 之间的任意一个及下划线,相当于 [a-zA-Z0-9_] 
 
W  不匹配大小写英文字符及数字 0 到 9 之间的任意一个,相当于 [^a-zA-Z0-9_] 
 
 匹配任何空白字符,相当于 [ f v] 
 
S  匹配任何非空白字符,相当于 [^s] 
 
d 匹配任何 0 到 9 之间的单个数字,相当于 [0-9] 
 
D  不匹配任何 0 到 9 之间的单个数字,相当于 [^0-9] 
 
[u4e00-u9fa5]  匹配任意单个汉字(这里用的是 Unicode 编码表示汉字的 ) 

三、正则表达式的分类

1、grep及基本正则表达式

grep [OPTION]... 'PATTERN' FILE...

        

字符匹配:

            . : 匹配任意单个字符

            []: 匹配指定集合中的任意单个字符

                [[:digit:]]===[0-9]

                [[:lower:]]===[a-z]

                [[:upper:]]===[A-Z]

                [[:alpha:]]===[a-zA-Z]

                [[:alnum:]]==[0-9a-zA-Z]

                [[:space:]]

                [[:punct:]]

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

        匹配次数:用于对其前面紧邻的字符所能够出现的次数作出限定

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

                例如:grep 'x*y'

                    xy, xxy, xxxy, y

            ?:匹配其前面的字符0次或1次;

                例如:grep 'x?y'

                    xy, xxy, y, xxxxxy, aby

            +: 匹配其前面的字符出现至少1次;

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

                例如:grep 'x{2}y'

                    xy, xxy, y, xxxxxy, aby

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

                例如: grep 'x{2,4}y'

                        xy, xxy, y, xxxxxxy, aby

                     grep 'x{0,4}y'

                         xy, xxy, y, xxxxxxxxxy, aby

                     grep 'x{2,}y'

                         xy, xxy, y, xxxxxy

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

        位置锚定

            ^: 行首锚定

                写在模式的最左侧

            $: 行尾锚定

                写在模式的最右侧

            ^$: 空白行

 

            <: 词首锚定, 相当于

                出现在要查找的单词模式的左侧;<char

            >:词尾锚定, 相当于

                出现在要查找的单词模式的右侧;char>

            <pattern>: 匹配单词

        分组:

            ()

            后向引用:模式中,如果使用()实现了分组,在某行文本的检查中,如果()的模式匹配到了某内容,此内容后面的模式中可以被引用;

                1, 2, 3

                模式自左而右,引用第#个左括号以及与其匹配右括号之间的模式匹配到的内容;

来个习题来形象的解释后向引用

习题: 添加用户bash, testbash, basher, nologin(SHELL为/sbin/nologin),而找出当前系统上其用户名和默认shell相同的用户;

 

    grep选项:

        -v: 反向选取

        -o: 仅显示匹配到内容

        -i: 忽略字符大小写

        -E: 使用扩展正则表达式

        -A #:打印后#行的内容

        -B #:打印前#行的内容

        -C #:打印#行的输出内容

2、egrep及其扩展正则表达式

egrep:egrep = grep -E 可以使用基本的正则表达外, 还可以用扩展表达式. 注意区别.
扩展表达式:

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

            字符匹配:

                . : 匹配其任意单个字符

                []: 匹配指定集合中的任意单个字符

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

            匹配次数限定:

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

                ?: 匹配其前面字符0次或1次;

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

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

                {m,n}:{m,}表示匹配其前面至少m次, {0,n}表示匹配其前面之多n次;

            锚定:

                ^: 行首锚定

                写在模式的最左侧

            $: 行尾锚定

                写在模式的最右侧

            ^$: 空白行

 

            <: 词首锚定, 相当于

                出现在要查找的单词模式的左侧;<char

            >:词尾锚定, 相当于

                出现在要查找的单词模式的右侧;char>

            <pattern>: 匹配单词

        分组:

            () ---------注意grep里的是用()

            后向引用:模式中,如果使用()实现了分组,在某行文本的检查中,如果()的模式匹配到了某内容,此内容后面的模式中可以被引用;

                1, 2, 3

                模式自左而右,引用第#个左括号以及与其匹配右括号之间的模式匹配到的内容;

            或者:

                a|b: a或者b

                ab|cd:

 

下面我来通过大量习题讲解来进一步揭开grep与egrep的神秘面纱

习题

1、显示/proc/meminfo文件中以大写或小写S开头的行;

            grep -i '^[s]'.* /proc/meminfo

            egrep ^[Ss].* /proc/meminfo

注释:知识点 (1) 这里用到了^: 行首锚定
(2)
[]: 匹配指定集合中的任意单个 字符

(3)-i: 忽略字符大小写

 

2、显示/etc/passwd文件中其默认shell为非/sbin/nologin的用户;

            grep -v /sbin/nologin$ /etc/passwd

         egrep -v /sbin/nologin$ /etc/passwd

注释:知识点 (1) -v: 反向选取

(2) $: 行尾锚定, 写在模式的最右侧

                

3、显示/etc/passwd文件中其默认shell为/bin/bash的用户;进一步:仅显示上述结果中其ID号最大的用户;    

grep /bin/bash /etc/passwd|sort -n -r -t: -k3 | head -1

 

 

注释:知识点 (1)sort [option…]

-n :按数值大小排序

-r :逆序

-t :指定字段以什么为分隔符

-k # :指定用于排序的第#字段

(2)head [options]

-n #或是-# :指定前#行

4、找出/etc/passwd文件中的一位数或两位数;

                 # egrep '<([0-9]|[1-9][0-9])>' /etc/passwd

注释:知识点 (1)     <pattern>: 匹配单词

5、显示/boot/grub/grub.conf中以至少一个空白字符开头的行;

#grep '^[[:space:]]+' /boot/grub/grub.conf

#egrep '^[[:space:]]+' /boot/grub/grub.conf

 

注释:知识点(1) 这里用到了^: 行首锚定
(2)     [[:space:]] 匹配任意单个空白字符

(3) 在grep里+:匹配其前面的字符至少1次;

(4) 在grep里+:匹配其前面的字符至少1次;

6、显示/etc/rc.d/rc.sysinit文件中,以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行;

grep    '^#[[:space:]]+[^[:space:]]+'     /etc/rc.d/rc.sysinit

注释:知识点与第五题一样

7、找出netstat -tan命令执行结果中以'LISTEN'(后可有空白字符)结尾的行;

netstat -tan | grep 'LISTEN[[:space:]]+' --color=auto

注释:知识点(1)netstat 命令用于显示各种网络相关信息

(2) | 为管道,连接命令,实现将前一个命令的输出当作后一个命令的输入;

(3) --color=auto 是增加颜色显示

(4)其它可参照第五题

8、扩展题:新建一个文本文件,假设有如下内容:

                He like his lover.

                He love his lover.

                He like his liker.

                He love his liker.

            找出其中最后一个单词是由此前某单词加r构成的行。

 

            # grep '(<[[:alpha:]]+>).*1r' a.txt

            # egrep '(<[[:alpha:]]+>).*1r' m.txt

注释:知识点(1) () ---grep的表示

            后向引用:模式中,如果使用()实现了分组,在某行文本的检查中,如果()的模式匹配到了某内容,此内容后面的模式中可以被引用;

                1, 2, 3

                模式自左而右,引用第#个左括号以及与其匹配右括号之间的模式匹配到的内容;

(2) () -------注意grep里的是用()

            后向引用:模式中,如果使用()实现了分组,在某行文本的检查中,如果()的模式匹配到了某内容,此内容后面的模式中可以被引用;

                1, 2, 3

                模式自左而右,引用第#个左括号以及与其匹配右括号之间的模式匹配到的内容;

9、显示当前系统上root、centos或user1用户的默认shell及用户名;下面几种表示方法

# cut -d: -f1,7 /etc/passwd | egrep ^'root|centos|user1'

# cut -d: -f1,7 /etc/passwd | egrep '^root|^centos|^user1'

# cut -d: -f1,7 /etc/passwd | egrep '^(root|centos|user1)'

如是有user10,则需要固定一个词

# cut -d: -f1,7 /etc/passwd | egrep '^(root|centos|<user1>)'

注释:知识点(1)cut option FILE…

-d 后边指定字段分隔符

-f # |#-# |#,# 指定要显示的字段(其中#表示第1段,#-#表示两#区间内连续的段落,(#,#)表示只要两个#段的本身)

(2)参照第五题的知识点

10、找出/etc/rc.d/init.d/functions文件中某单词后面跟一对小括号"()"的行;

#grep    '<[[:alnum:]]+>()' /etc/rc.d/init.d/functions|cut -d' ' -f1

    #egrep    '<[[:alnum:]]+>()' /etc/rc.d/init.d/functions|cut -d' ' -f1

注释:知识点(1) [[:alnum:]]==[0-9a-zA-Z]

(2) 在grep里+:匹配其前面的字符至少1次;

(3) 在grep里+:匹配其前面的字符至少1次;

(4)在egrep里小括号()表示词组引用,所以想表示小括号的原义需要转义-- ()

11、使用echo输出一个路径,而使用egrep取出其基名;

     #echo '/etc/sysconfig/' | egrep -o '[^/]+/?$'

注释:知识点(1)基名(dirname):从文件名中去掉路径信息,只打印

(2) -o: 仅显示匹配到内容

(3)     ?: 匹配其前面字符0次或1次;

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

     1.0.0.1 - 223.255.255.254

ifconfig | egrep '[0-9]|[1-9][0-9]|[1-9][0-9]{2}'

--color=auto

注释:知识点(1)在egrep中

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

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

    ifconfig |egrep '<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-1][0-9]|22[0-3])>.<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>.<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>.<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])>' --color=auto

注释:知识点(1)四种颜色表示ip的四个段落,

(2)我们也可以简化下,因为第二段和第三段一样,效果如下:

ifconfig |egrep '<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-1][0-9]|22[0-3])>.(<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>.){2}<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])>' --color=auto

原文地址:https://www.cnblogs.com/na2po2lun/p/4146652.html