正则表达式:正则表达式(regular expression,RE)是一类由特殊字符组合起来的一种字符模式,用于在查找过程中匹配特定的字符。
元字符:元字符是这样的一类字符,它们不表示字符本身的含义,而用于额外功能性的描述意义。
GNU/linux 下常见两种元字符,一种是shell元字符,一种是正则表达式元字符,它们各司其职,shell元字符由linux shell程序来解析,正则表达式元字符则由执行此匹配模式的程序来解析,比如vim、grep、awk等。
shell元字符
* 匹配任意字符串,例:# ls /etc/p* 列出目录/etc/下以p开头的任意文件
? 匹配任意单个字符,例:# ls /etc/p? 列出目录/etc/下以p开头,后跟只有一个字符的文件
[] 匹配括号中的任意一个字符,例:[.,;] 匹配点号或逗号或分号
[-] 匹配括号中一个范围内的任意一个字符,例:[a-z] 匹配任意一个小写字母
[!] 匹配括号字符之外的任意一个字符,例:[!abc] 匹配字符a、b、c之外的任意一个字符
基本正则表达式元字符
常用元字符(matecharacter):
^:脱字符,锚定行首的符合条件的内容,用法^pattern
$:锚定行尾的符合条件的内容,用法pattern$
^$:匹配空白行
^pattern$:精确匹配pattern
. :点号,匹配任意单个字符
* :匹配紧挨在其前面的字符任意次,有数量的概念
.* :匹配任意长度的任意字符(不包含换行符),此匹配是工作在贪婪模式下,尽可能 长的去匹配符合条件 的内容
[]:匹配指定范围内的任意单个字符
[^]:匹配指定范围外的任意单个字符
\{m,n\}:匹配其前面的字符至少m次,至多n次
\{0,n\}:匹配其前面的字符至多n次
\{m,\}:匹配其前面的字符至少m次
\< :锚定词首
\> :锚定词尾
扩展正则表达式元字符
基本正则表达式里的元字符在扩展正则里也同样适用,只是增加了以下一些元字符。
增加的元字符:
+:匹配其前面的字符至少1次
?:匹配其紧挨着前面的字符0次或1次
x{m}:字符x重复m次
x{m,}:字符x重复至少m次
x{m,n}:字符x重复m-n次
():分组,支持引用
|:表示或者
方括号类字符
[:alpha:] 所有字母字符,包括大小写
[:upper:] 所有大写字母字符
[:lower:] 所有小写字母字符
[:digit:] 所有数字字符
[:alnum:] 所有数字与字母字符
[:space:] 所有空白字符,包括空格、换行符、制表符
[:punct:] 所有标点字符
[:graph:] 所有非空白字符,不包含空格、控制字符
[:print:] 与[a:graph:]类似,但包含空格字符
[:cntrl:] 控制字符
[:xdigit:] 十六进制数字字符
小结:扩展的正则表达式也可以在基本正则表达式中使用,只要在元字符前加上“\”转义符即可,如“\+”“\|”等。正则表达式也只是一种特殊的模式匹配而已,它要想工作起来也必须要利用一些工具才行,比如:vim、grep、sed、awk等。
常用正则使用举例:
以下的例子都是从网上转载,只是对这些正则表达式进一步进行了分析,来源:http://deerchao.net/tutorials/regex/common.htm
1、匹配一个网址(URL)
表达式:[a-zA-Z]+://[^\s]*
分析:“[]”表示匹配方括号内的任何字符;[a-zA-Z]表示匹配26个英文字母中的任何一个,且不分大小写;“+”号表示前一个元素可出现1次或多次,所以“[a-zA-Z]+”表示方括号中的字符可以出现1次或多次,这部份在URL中表示是协议部份;“://”是URL中的固定格式;“[^\s]*”表示匹配非空白字符任意次,包含零次。
实例:
[root@zcj test]# cat jj.txt HTTP://www.baidu.com http://www.BAIDU.com http://www.baidu.com https://www.baidu.com thx://www.baidu.com
2、匹配IP地址
表达式:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
分析:IPV4地址是由四个点号分隔成的四个十进制位,称为点分十进制,每一组的取值范围是0-255(包括网络地址和广播地址),那么这个范围要分成几种情况才能匹配完,把0-255这个范围分成0-199、200-249、250-255三组,“[01]?\d\d?”正好匹配0-199,“2[0-4]\d”正好匹配200-249,“25[0-5]”匹配250-255;能把这一部份理解清楚,那上边的匹配IP地址的表达式也就能理解了。
实例:
不知道什么原因,系统里的egrep不能识别“\d”这个模式,只好换成“[0-9]”,效果也是一样的。
3、匹配Email地址
表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
分析:这个表达式写得比较复杂,把不常见的格式也匹配了,比如会把“sky+33@163.com-cn”这样的邮件地址也会匹配到,而我们常见的邮件地址会是“sky@sina.com.cn”“sky12@163.com”“sky_23@126.cn”“12345@sina.com”这样类似的例子。先来拆分上边表达式中各部份的意义:“\w”这个非常有意思,它表示与任何单词字符匹配(我的理解就是一个单个字符),但不会匹配到“+”“-”“.”等字符,但会匹配到“_”,并且匹配到的是单个单词字符,所以“\w+”会匹配到多个单个字符组成的字符串;“([-+.]\w+)*”表示在三个特殊符号后边跟上了任何单词字符,后边整体跟上了一个“*”号,表示这样的模式可以出现任何次数,包括零次,这样就比较符合在邮件地址格式中@符号的前部份了;“([-.]\w+)*\.\w+([-.]\w+)*”后边的这个表达式分成了两部份,且都是用“*”号来进行对前边的小括号内的匹配模式进行次数匹配,这样模式就写得非常有灵活性,可以匹配到类似“@163.com”的,也可以匹配到“@163.com.cn”的,不得不佩服正则表达式的强大。
实例:
[root@zcj test]# cat mail.txt sky_551@163-com sky@126.com.cn sky.551@sina.com-cn sky+551@sina.com sky-551@sina.com sky_22@sina sky5511@yaho.cn d 3 ) _ ~ 2222@13.com
4、匹配qq号码
表达式:[1-9]\d{4,}
分析:[1-9]表示1-9这9个数字中的任何一个,“\d”表示匹配“0-9”间的任何一个数字,相当于[0-9]这个模式,{4,}这个表示其前边的字符至少出现4次。那这个表达款就能匹配到长度是大于等于5的qq号码。
5、匹配“年-月-日”
表达式:(\d{4}|\d{2})-((1[0-2])|(0?[1-9]))-(([12][0-9])|(3[01])|(0?[1-9]))
分析:(\d{4}|\d{2})表示年可以是4位的年,也可以是2位的年;((1[0-2])|(0?[1-9]))表示把月分成两种可能,一种是1到9月这种一位的年,也可写成“01-09”这种月的格式,另一种是10月至12月,这种两位的月;(([12][0-9])|(3[01])|(0?[1-9]))表示把日分成了三种可能,因为一个月最长有31天,把31天分成以下几种可能,一是1-9号,二是10-29号,三是30-31号。“0?[1-9]”表示1-9号(也可01-09),“[12][0-9]”表示10-29号,“3[01]”表示30-31号。
实例: