正则表达式的应用

正则表达式Regular Expression

 

一、        什么是正则表达式

1.1 正则表达式简介

       所谓正则表达式,实际上就是用来描述某些字符串匹配规则的工具,简单地说,正则表达式是对文本进行过滤的工具。而正则表达式之所以拥有过滤文本的功能,是因为它定义了一系列的元字符,通过元字符配合其他普通字符来表达出一种规则(匹配规则),只有符合该规则的文本才能保留下来。由于正则表达式语法简练、功能强大,得到了许多变成语言的支持,包括Java、C++、Perl以及Shell。

       比如ls .txt。通常情况下,我们称“*”为通配符。当shell遇到该符号时,会将其解释为“任意的字符串”。与通配符类似,正则表达式也是用来匹配文本的,与之相比,正则表达式能够更加准确的描述用户的需求。

       正则表达式在Unix和Linux中得到广泛的应用,常见支持正则表达式的Unix工具如下:

       grep命令族:用于匹配文本行

       sed流编辑器:用于编辑文本

       awk:用于处理字符串的语言

       掌握正则表达式,可以更好地利用这些工具。

 

1.2 如何学习正则表达式

       1)重点在于理解元字符

       元字符在正则表达式中占核心地位,正则表达式最终是由元字符表达出来。理解和掌握元字符的涵义,才能达到灵活运用的地步。

 

       2)掌握好正则表达式的语法

       正则表达式之所以简练,是因为它有严格的语法。例如*”它匹配该符号前面那一个普通字符出现0次或多次,也就是说,它的作用范围仅限于紧挨着该字符前面的一个字符。

 

二、        基本正则表达式(Basic Regular Expression,BRE)

       又称标准的正则表达式,是最早指定的正则表达式规范,其所定义的元字符主要有以下几种:

1、            行首定位符 “^”

 

2、            行尾定位符 “$”

 

3、            单个字符匹配 “.”

                            匹配任意单个字符,包括空格,但不包括换行符“\n”

4、            限定符 “*”

                            匹配其前导字符可以出现任意次数(0次或多次)

5、            字符集合匹配 “[]”

                            匹配方括号中任意一个字符        //例如:[abc]、[0-9]、[A-Z]

6、            字符集合不匹配 “[^]”

                            不匹配其中列出的任意字符

 

在示例之前,先来用sed删除空行:

       [root@mha_master opt]# sed -i "/^$/d" regexp.txt

 

示例1:过滤出以字母“a”开头的行

       [root@mha_master opt]# grep "^a" regexp.txt

 

示例2:过滤出以“C”结尾的行

       [root@mha_master opt]# grep "C$" regexp.txt

 

示例3:过滤出总共有3个字符,该字符串以’a’开头,紧跟着第二个字符是“b”,第三个字符也是最后一个字符为“c”的行

       [root@mha_master opt]# grep '^abc$' regexp.txt      

      

示例4:匹配以a开头,c结尾,中间为除了换行符之外的任意一个字符的行

       [root@mha_master opt]# grep '^a.c$' regexp.txt

 

示例5:匹配以d开头,d结尾,中间为除了换行符之外的任意两个字符的行

       [root@mha_master opt]# grep '^d..d$' regexp.txt             //可以使用多个“.”匹配多个字符

 

示例6:匹配a和b之间没有s或者有多个s的行

       [root@mha_master opt]# grep '^as*b$' regexp.txt

 

示例7:匹配出字符串,该字符串只有三个字符且以字母开头、第二个字符是数字,第三个字符为字母。

       [root@mha_master opt]# grep '^[a-zA-Z][0-9][a-zA-Z]$' regexp.txt

 

示例8:只匹配出来“a8c”

       [root@localhost 桌面]# grep '^a[^a-z]c$' regexp.txt

       a c

       a.c                 //前两行结果明显不符合期望

       a8c

       [root@mha_master opt]# grep '^a[^a-z|\.|\ ][a-z]$' regexp.txt

 

其他标准正则表达式支持的元字符

7.次数匹配—数量词

x\{m,n\}     

       区间表达式(次数匹配),匹配字符x重复的次数区间。该表达式表示x最少重复m次,最多重复n次

x\{m,\}

       表示x至少重复出现m次

x\{,m\}

       表示x至多重复出现m次

x\{m\}

       表示x重复m次

 

\{\}示例:

[root@localhost 桌面]# grep '^as\{2,3\}b$' regexp.txt

assb

asssb

[root@localhost 桌面]# grep '^as\{2,\}b$' regexp.txt

assb

asssb

[root@localhost 桌面]# grep '^as\{2\}b$' regexp.txt

assb

 

匹配出abbbbbc

[root@localhost 桌面]# grep '^ab\{5\}c$' regexp.txt

abbbbbc

 

匹配出电话号码(11位)

[root@A tmp]# cat 1.txt 
ab
asb
assb
asssb
13912345678
18198765432
39718973748719749]
313141
[root@A tmp]# grep '^[0-9]\{11\}$' 1.txt 
13912345678
18198765432

 

8.词首词尾匹配

\<  

       词首定位符,\取其转义之意,< 前,首,词首

\>

       词尾定位符,\取其转义之意,> 后,尾,词尾

 

词首字、词尾子匹配符示例:

[root@mha_master opt]# grep "\<welcome" regexp.txt

welcome to vfast!

[root@mha_master opt]# grep "done\>" regexp.txt

well done!

 

9.向前引用 \(\)

       定义字表达式的开始和结束位置,在后续正则表达式中可以通过转义字符来引用正则表达式。最多可以定义9个字表达式,通过\1~\9来引用。

       如:

       [root@localhost 桌面]# grep '\(love\).*\1' regexp.txt

       love me tender,love me sweet!

       字表达式\(love\).*\1,表示匹配两个love中间包含任意个字符的文本行,其中\1表示引用前面定义的第一个字表达\(love\)

 

三、        扩展的正则表达式(Extended Regular Expression,ERE)

       扩展的正则表达式支持比标准的正则表达式更多的元字符,扩展的正则表达式对有些标准正则表达式所支持的元字符并不支持(区间表达式次数匹配),但上面介绍的6种元字符是支持的,并且意义完全相同。下面重点来看下扩展的正则表达式中新增的元字符。

Unix命令:

       egrep或者grep -E 、 sed -r

 

1)            限定符 “+”

                     限定前面的字符至少出现一次

限定符 “*限定前面的字符出现0次或多次

2)            限定符 “?”

                     限定前面的字符出现0次或1次

 

3)            竖线“|”和小括号“()”

                     竖线“|”表示多个表达式之间“或”的关系,语法为:

       expression1|expression2|expression3…

                     小括号(分组)表示一组可选值的集合。竖线和小括号经常放在一起用,表示一组可选值。

 

4)            扩展正则表达式取消了次数匹配{m,n}语法中的转义符,在使用这种语法时,不需要再添加转义符也不能添加,添加会匹配失败。

      

总结:标准正则表达式元字符:^  $  .  *  []  [^]    \{\} 

           扩展正则表达式元字符:+  ?  “|”和“()”  {}  

 

示例1:匹配出a和c之间字符“c”至少出现1次的字符串

       [root@localhost 桌面]# grep '^ac+c$' regexp.txt      //基本正则写(不支持+符号),不行

       [root@localhost 桌面]# grep -E '^ac+c$' regexp.txt        //还得扩展的正则

       acc

       accc

 

示例2:匹配a打头,b结尾,中间有0个或一个s的字符串

       [root@mha_master opt]# grep -E '^as?b$' regexp.txt

 

示例3:匹配字符串,该字符串共有三个字符,a打头,c结尾,中间是数字或者是字符

       [root@mha_master opt]# grep -E '^a([a-z]|[0-9])c$' regexp.txt

    或 [root@mha_master opt]# grep -E '^a([a-z0-9])c$' regexp.txt

       如果还有大写字母:

       [root@mha_master opt]# grep -E '^a([a-zA-Z0-9])c$' regexp.txt

标准正则中[]表示匹配其中的任意一个字符,也可用竖线加小括号来表达:

       [abc]     等价于  (a|b|c)

下面三组也是等价的:

       (Jeffrey|Jeffery)

       Jeff(rey|ery)

       Jeff(re|er)y

 

示例4:字符串a开头,b结尾,中间s至少出现一次,最多出现2次

[root@mha_master opt]# grep -E '^as{1,2}b$' regexp.txt

      

四、        正则表达式中的普通字符

       正则表达式是由一系列字符组成,其中包括元字符和普通字符。前面看过了很多元字符,现在来了解普通字符该如何匹配。

       通常情况下,普通字符通常结合方括号表达式表示:

       [cC]hina

       [^hello]

       [a-zA-Z]

       [0123456789]

       [0-9]

       除了这些之外,还可以使用posix字符集,POSIX字符集是为了在不同国家的字符编码中保持一致,而定义的一些特殊字符类(扩展的正则):

字符类

说明

[:alnum:]

匹配任意一个字母或数字,等价于[a-zA-Z0-9]

[:alpha:]

匹配任意一个字母,等价于a-zA-Z

[:digit:]

匹配任意一个数字,等价于0-9

[:lower:]

匹配任意一个小写字母,等价于a-z

[:upper:]

匹配任意一个大写字母,等价于A-Z

[:space:]

匹配任意一个空白字符,包括空格、制表符、换行符

[:blank:]

匹配空格和制表符

[:graph:]

匹配任意一个看得见的可打印字符,不包括空白字符

[:print:]

匹配任意一个可以打印的字符,包括空白字符,但是不包括控制字符、EOF文件结束符

[:cntrl:]

匹配任意一个控制字符(百度百科:控制字符),即ACSII字符集中的前32个字符,如:换行符、制表符等

[:punct:]

匹配任意一个标点符号,如”[]”、”{}”、 ,“”

[:xdigit:]

匹配16进制数,即0-9、a-f以及A-F

 

单词:

       alphabet      字母表

       digit       数字

       blank     空白的

       punctuation              标点符号

 

示例:过滤出符合指定格式的电话号码

       [root@mha_master opt]# grep -E '400-[[:digit:]]{3}-[[:digit:]]{4}$' regexp.txt

       400-123-5678

 

运算符的优先级:

运算符

说明

\

转义字符

[]

方括号表达式

()

分组

*、+、?、{m}、{m,}、{m,n}

限定符

普通字符

按照从做到右的顺序

^、$

定位符

|

或运算

 

 

演示分组“()”:匹配IP地址

[root@mha_master opt]# grep -E '^([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}$' regexp.txt

202.106.0.20

10.0.0.1

256.45.32.1        //这是一个不正确的IP

 

精确匹配:

grep -E "^([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" regexp.txt

 

 

 

练习:

1、从regexp.txt中匹配出书写正确的邮箱地址:

              这里认为邮箱用户名至少是6~18位的字母和数字组成,邮箱账号均为163.com的邮箱。

       [root@mha_master opt]# grep -E '^[[:alnum:]]{6,18}@163\.com$' regexp.txt

 

2、源文件url.txt的内容如下:

www.baidu.com
http://www.baidu.com
https://www.baidu.com
http://wwwbaiducom
baidu.com
baidu

 

匹配出以http或https开头,其后为“:”,并且含有“.”的串

[root@localhost 桌面]# grep -E 'https?.*\.'  url.txt

http://www.baidu.com

https://www.baidu.com

 

3、Email匹配

示例文件内容为:

hfutwyy@qq.com
aaaa@
aaa@.com
_aaa@gmail.com

@@baidu.com

匹配以字母数字或者下划线开头的多个字符,其后有一个@之后有多个字母数字或者下划线,其中有一个.号

[root@localhost 桌面]# grep -E '^[[:alnum:]|_]*@[[:alnum:]|_]\.*' email

hfutwyy@qq.com

_aaa@gmail.com

 

4、匹配身份证号:18位

前17位必须为数字,最后一位是数字或字母

grep -E '^[0-9]{17}[0-9A-Z]$' danny.txt

 

5、校验用户名

 

[root@localhost 桌面]# grep -E '^[[:alpha:]][[:alnum:]|_]{5,17}@163.com' regexp.txt

heihei@163.com

 

posted @ 2018-01-16 18:18  叮伱格斐呃  阅读(2474)  评论(0编辑  收藏  举报
Live2D