在CentOS6系统中使用grep命令结合正则表达式搜索文本行
第10章 正则表达式
10.1 正则表达式基础
10.1.1 什么是正则表达式
正则表达式就是能用某种模式去匹配一类字符串的公式,它是由一串字符和元字符构成的字符串。
10.1.2 基础的正则表达式
“.”(一个点)符号
点符号用于匹配除换行符之外的任意一个字符。例如:r.t可以匹配rot、rut,但是不能匹配root,
若使用r..t就可以匹配root、ruut、r t(中间是两个空格)等。
例:从/etc/passwd中搜索出“包含r,紧跟着两个字符,后面再接t”的行。
[kangyp@centos6 Documents]$ grep 'r..t' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin [kangyp@centos6 Documents]$
“*”符号
“*”符号用于匹配前一个字符0次或任意多次,比如ab*,可以匹配a、ab、abb等。
“*”号经常和“.”符号加在一起使用。比如“.*”代表任意长度的不包含换行的字符。
例:‘r.*t’,代表查找包含字母r,后面紧跟任意长度的字符,再跟一个字母t的行。
“\{n,m\}”符号
\{n\}匹配前面的字符n次。
例:匹配的是包含root的行(r和t中包含两个o)
[kangyp@centos6 Documents]$ grep 'ro\{2\}t' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [kangyp@centos6 Documents]$
\{n,\}匹配前面的字符至少n次以上(含n次)
例:匹配的是包含rt、rot、root……的行
[kangyp@centos6 Documents]$ grep 'ro\{0,\}t' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin rtkit:x:499:499:RealtimeKit:/proc:/sbin/nologin vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin [kangyp@centos6 Documents]$
\{n,m\}匹配前面的字符n到m次。
“^”符号
这个符号位于键盘数字6的上面,又称尖角号。这个符号用于匹配开头的字符。
比如说“^root”匹配的是以字母root开始的行。
“$”符号
“$”用于匹配尾部,比如说“abc$”代表的是以abc结尾的行。
如果是“^$”则代表该行为空,因为^和$间什么都没有。
例:匹配的是以r开头,中间有一串任意字符,以h结尾的行。
[kangyp@centos6 Documents]$ grep '^r.*h$' /etc/passwd root:x:0:0:root:/root:/bin/bash [kangyp@centos6 Documents]$
“[]”符号
这是一对方括号,用于匹配方括号内出现的任一字符。比如说单项选择题的答案,可能是A、B、C、D选项中的任意一种,用正则表达式表示就是[ABCD]。
如果遇到比较大范围的匹配,比如说要匹配所有字母则写成[A-Za-z],此处要使用“-”号做范围限定。
如果是要匹配不是大写字母A、B、C、D的字符又该怎么写呢?还记得上面的“^”号吗,如
果这个符号出现在[]中,则代表取反,也就是“不是”的意思。那这里的写法就是[^A-D]
“\”符号
这个符号代表转义字符,我们可以对很多特殊的字符进行“转义”,让它只代表字符本身
例:如果想要匹配任意长度的点号呢?
这时使用转义字符就对了:“\.*”
“\<”符号和“\>”符号
这两个符号分别用于界定单词的左边界和右边界。比如说“\<hello”用于匹配以“hello”开头的单词;而“hello\>”则用于匹配以“hello”结尾的单词。
还可以使用它们的组合——“\<\>”用于精确匹配一个字符串。所以“\<hello\>”可精确匹配单词hello,而不是helloworld等。
[root@localhost ~]# echo "hello" | grep '\<hello\>'
hello
[root@localhost ~]# echo "hellod" | grep '\<hello\>'
[root@localhost ~]# #没有输出,表示匹配不成功
以上讲的是8种常见的元字符
“\d”符号
匹配一个数字,等价于[0-9] ,使用grep匹配这种正则表达式时可能会遇到无法匹配的问题。
这是因为“\d”是一种Perl兼容模式的表达式,又称作PCRE,要想使用这种模式的匹配符,需要加上-P参数,示例如下:
[root@localhost ~]# echo 123 | grep -P '\d' 123 # 这样就匹配成功了
“\b”符号
匹配单词的边界,比如“\bhello\b”可精确匹配含有“hello”单词的行。
“\w”符号
匹配字母、数字和下划线,等价于[A-Za-z0-9]
“\n”符号
匹配一个换行符。
“\r”符号
匹配一个回车符。
“\t”符号
匹配一个制表符。
“\f”符号
匹配一个换页符。
“\s”符号
匹配任何空白字符。
“\S”符号
匹配任何非空白字符。
10.1.3 扩展的正则表达式
在使用这些扩展符号时,需要使用egrep命令。
“?”符号
“?”符号用于匹配前一个字符0次或1次,所以“ro?t”仅能匹配rot或rt。
“+”符号
“+”符号用于匹配前一个字符1次以上,所以“ro+t”就可以匹配rot、root等。
“|”符号
“|”符号是“或”的意思,即多种可能的罗列,彼此间是一种分支关系。
“()”符号
“()”符号通常需要和“|”符号联合使用,用于枚举一系列可替换的字符。
比如说固定电话的区号和电话号码之间,可能用“-”符号或者用一个空格连接。
^0[0-9]\{2,3\}(-| )[0-9]\{8\}
使用"()"和"|"匹配hard、hold或hood
h(ar|oo|ol)d
10.1.4 通配符
通配符是一种特殊的语句,主要包含“*”号和“?”号(还有“{}”、“^”、“!”)
主要用来模糊搜索文件,使用它替代一个或多个真正的字符,尤其是在不知道或者不确定完整的文件名时,用来匹配符合条件的文件。
“*”符号
这里的“*”就是提到的第一个通配符,代表0个或多个字符。
那么之前的*.doc就是指所有以.doc结尾的文件。如果想要找的文档是以字母A开头,则可用A*.doc来查找。
“?”符号
当它作为通配符使用时,代表的是任意一个字符。
“{}”符号
“{}”可拥有匹配所有括号内包含的以逗号隔开的字符。
例如,下面列出了所有以字母A、B、C开头,以.doc结尾的文件:
[root@localhost ~]# ls -l {A,B,C}.doc
有 意 思 的 是 , “{}” 还 支 持 嵌 套 的 通 配 。
[root@localhost ~]# ls -l {[A-Z]*.doc,[0-9]??.txt}
“^”符号和“!”符号
这两个符号往往和“[]”一起使用,当出现在“[]”中的时候,代表取反。
10.2 正则表达式示例
在前面的第5章中,我们了解了grep的一些基本用法,但是它的功能还远远不止这些。
grep的 英 文 是 Global search Regular Expression and Print out the line,即全面搜索正则表达式并打印出匹配行。通过本章前面的一些实例我们也看到,grep和正则表达式结合使用后产生了强大的搜索效果。
提醒一下读者,由于正则表达式中含有较多特殊的字符,所以结合grep时,最好使用单引号将正则表达式括起来,以免造成错误。
为了演示grep命令的用法,首先创建一个文件RegExp.txt,文件内容如下所示:
----TEXT BEGIN---- good morning teacher hello world is a script gold sunshine looks beautiful golden time flies god bless me what a delicious food they teast Good you fell glad wrong word gooood wrong word gl0d wrong word gl2d wrong word gl3d www.helloworld.com www@helloworld@com Upper case 100% means pure php have a gd module -----TEXT END-----
1)使用“^”匹配行首,示例如下:
#搜索以good开头的行
grep '^good' RegExp.txt
2)使用“$”匹配行尾,示例如下:
#搜索以Good结尾的行
grep 'Good$' RegExp.txt
3)使用“^$”组合,匹配空行,下面的命令可计算文件中共有多少行空行:
grep -c '^$' RegExp.txt
4)使用方括号匹配多种可能,示例如下:
#搜索包含Good和good的行
grep '[Gg]ood' RegExp.txt
5)在方括号中使用“^”做反选,示例如下:
#搜索一个包含ood的行,但是不能是Good或good
grep '[^Gg]ood' RegExp.txt
6)使用“.”号,示例如下:
#搜索包含一个词,该词以g开头、紧接着是两个任意字符、再接着是一个d的行
grep 'g..d' RegExp.txt
#搜索包含一个词,该词以G或g开头、紧接着是两个任意字符、再接着是一个d的行
grep '[Gg]..d' RegExp.txt
#搜索这样一些行,该行包含某个单词,该词满足如下条件:
#1.
第一个字符可以是G或g
#2.
第二个字符可以是l或o
#3.
第三个字符可以是换行符之外的任意字符
#4.
第四个字符一定是d
grep '[Gg][lo].d' RegExp.txt
7)使用精确匹配,示例如下:
#搜索含有gold的行,从搜索结果中发现golden也被匹配出来了
#现在我们需要精确匹配含有gold这个单词的行
grep '\<gold\>' RegExp.txt
# 用“\b”的效果和“\<\>”一致
grep '\bgold\b' RegExp.txt
8)使用“*”号,示例如下:
#
搜索这样一些行,该行包含某个单词,该词满足如下条件:
#1.以g开头
#2.g后面跟零到无限个o
#3.零到无限个o后面跟d
grep 'go*d' RegExp.txt
10)使用“-”号,示例如下:
#
文件中有一些拼写错误的单词,发现是把glod中的o字母写成数字0了
grep 'gl[0-9]d' RegExp.txt
11)使用“\”做字符转义,示例如下:
#搜索文件中包含域名www.helloworld.com的行
#这里将点做转义,则输出的结果满足预期
grep 'www\.helloworld\.com' RegExp.txt
12)使用“\{\}”号,示例如下:
#
文档中有一个单词good被拼写错了,多写了几个o
#
搜索以字母g开头包含两个以上o的单词
grep 'go\{2,\}d' RegExp.txt
#
搜索以字母g开头,中间正好包含4个o的单词
grep 'go\{4\}' RegExp.txt
13)特殊的POSIX字符,示例如下:
#grep支持一类特殊的POSIX字符,列举如下
#[:upper:]
大写字符
#[:lower:]
小写字符
#[:digit:]
数字字符
#[:space:]
所有空白字符(新行,空格,制表符)
#[:print:]
非空字符(包括空格)
#[:punct:]
标点符号
#搜索以大写字母开头的行
grep ^[[:upper:]] RegExp.txt
#搜索以数字开头的行
grep ^[[:digit:]] RegExp.txt
14)使用扩展的正则表达式egrep,示例如下:
#
搜索g和d之间至少有一个o的行
egrep 'go+d' RegExp.txt
#搜索g和d之间只有0个或1个o的行(0次或1次)
egrep 'go?d' RegExp.txt
#
搜索有glad或gold的行
egrep 'glad|gold' RegExp.txt
#
搜索有glad或gold的行的另一种写法
egrep 'g(la|ol)d' RegExp.txt
只有不断地多读多用,才能较为深刻地理解正则表达式。
参考资料:
Linux系统命令及Shell脚本实践指南:第10章 正则表达式