接触Linux的时间不长,从第一周的悠悠然学习,到现在的神经紧绷,晕晕乎乎,仿佛过山车一般,开始的“美好”总是那么短暂,而后的刺激一波未平一波又起。


   在学习Linux前行的道路上,第一个拦路虎恐怕是就是令人烦恼的文本检索了,冗长的字符串、动辄成千上万行的日志文件,想从中找到你想要的那一条或者多条,实在是不容易。Linux的提供给我们了一个强大的命令grep。通过grep命令与通配符、正则表达式的组合,可以轻松的从看似杂乱的一行行文本行中检索出来。可是,这么强大的命令,想要学好,却不是喝水吃饭那么容易。必须要深入的理解,多加练习,才能真正的学会使用它。下面,我做一个初级的Linux学习者,总结下自己的浅薄认识,一来锻炼自己,二则分享给大家,如果纰漏错误,还望指正。


   在下面的总结中,文本搜索多使用/etc/passwd做演示,各位小友也可以使用其他的文本文件自行测试验证。

   本文的主要内容包括以下内容:


   什么是grep命令

   grep命令格式及说明

   常用选项及示例

   匹配模式之正则表达式

   匹配模式之扩展正则表达式


一、什么是grep命令

    grep(global search regular expression_r(RE) and print out theline),这是一个典型的文本搜索工具,根据用户指定的文本模式对目标文件进行逐行搜索,显示能够被模式所匹配到的行。通俗来所就是,给grep命令一个模板,它会按照这个模板在文本里一行一行的扫描,搜索到的结果被送到屏幕,不影响原文件内容。与之相近的命令egrep、fgrep的功能,均可以通过grep命令与不同的选项组合实现,因此在本文中,不在单独详细介绍。


二、grep命令格式及说明


   格式:grep [options] ‘PATTERN’ file,…

   说明:PATTERN是搜索文本的关键,grep用PATTERN正则表达式来搜索文本中的每一行,在贪婪的模式下(命令尽可能多的匹配行内的字串),尽力去匹配。


三、常用选项及示例


--color=auto  -n 将搜索出的符合条件的行的匹配上的字符自动着色显示;显示行号
-v反向查找,显示出不能被模式匹配到的行
-E
支持扩展正则表达式
-i
不区分字符大小写
-o
仅显示被模式匹配到的字串,而非整行
-A #
显示被匹配到的行,包括它之后的#行(#表示正整数)
-B #显示被匹配到的行,包括它之前的#行(#表示正整数)
-C #显示被匹配到的行,包括它前后的#行(#表示正整数)

   示例

   1.-n 显示文本所在的行号,搜索以nologin结尾的行。


[root@station47 tmp]# grep --color=auto -n "nologin$" /etc/passwd
2:bin:x:1:1:bin:/bin:/sbin/nologin
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin


   2.-v 反向显示。显示不是以nologin为结尾的行


[root@station47 tmp]# grep --color=auto -n -v  "nologin$" /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
6:sync:x:5:0:sync:/sbin:/bin/sync
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8:halt:x:7:0:halt:/sbin:/sbin/halt


   3.-i 不区分大小写。显示以root为开头的行。


[root@station47 tmp]# grep --color=auto -i "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
Root:x:500:500::/home/Root:/bin/bash


   4.-o 只显示匹配的字串,而不是整行。显示以root开头的行


[root@station47 tmp]#  grep --color=auto -o "^root" /etc/passwd
root
[root@station47 tmp]#


   5.-A # 显示匹配到行的后#行。搜索以ftp开头的行


[root@station47 tmp]# grep --color=auto -A 3 "^ftp" /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
[root@station47 tmp]#


   6.-B # 显示匹配到行的前#行。搜索以ftp开头的行


[root@station47 tmp]# grep --color=auto -B  3 "^ftp" /etc/passwd
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@station47 tmp]#


四、匹配模式之基本正则表达式


   在grep命令格式中的PATTERN正则表达式是重点和难点。学好正则表达式,“走遍天下都不怕”,在vim的末行模式等场景下,正则表达式都有出色的表现。这里总结正则表达式元字符(不表示字符本身的意义,用于额外功能性的描述)。并辅以实例说明。在原元字符中经常可以看到的\,是转义符。在扩展正则表达式中是不需要的。


   1.字符匹配


.任意单个字符
[]指定范围内的任意单个字符,

[0-9], [[:digit:]]

[a-z], [[:lower:]]

[A-Z], [[:upper:]]

[[:alpha:]]

[[:alnum:]]

[[:space:]]

[[:punct:]]   类似通配符里的内容

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

   此处建立实验用文本test.txt,test1.txt内容为  

#test.txt
abc
abcd
aaaa
acdgssd
sddes
dseega


   1-1 . 匹配任意单个字符。


[root@station47 ~]# grep --color=auto "a.c" /tmp/test.txt
abc
abcd
[root@station47 ~]#

   注:这里要匹配到a与c中间有一个任意字符的行


   1-2 []指定范围内的任意字符。查找所有包含s或g的字串


[root@station47 ~]# grep --color=auto "[sg]" /tmp/test.txt
acdgssd
sddes
dseega
[root@station47 ~]#


   注:这里查找到了,a或者b开头的行,[ab]二者选其一。其他类似,不再一一列举。


   1-3 [^] 指定范围外的任意单个字符。搜索不包含a的字串


[root@station47 ~]# grep --color=auto "[^a]" /tmp/test.txt
abc
abcd
acdgssd
sddes
dseega
[root@station47 ~]#


    2.次数匹配


   此处的匹配的次数指的是元字符前面的那个字符。


*
匹配其前面的字符任意次
\?匹配其前面的字符0次或1次
\{m\}匹配其前面的字符匹配m次
\{m,n\}匹配其前面的字符至少m次,至多n次
\{m,\}匹配其前面的字符至少m次
\{0,n\}匹配其前面的字符至多n次

   实验文本test1.txt


#test1.txt
xxy
xy
y
xxy

   2-1 *  任意次数。


[root@station47 ~]# grep --color "x*y" test1.txt
xxy
xy
y
xxy
[root@station47 ~]#


   注:y前面可以出现任意个x,包括0个


   2-2 \? 0次或1次


[root@station47 ~]# grep --color "roo\?t" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@station47 ~]#

   注:root,o出现了一次


   2-3 \{m\}匹配m次。


[root@station47 ~]# grep --color "ro\{2\}t" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@station47 ~]#


   注:出现两次o


   2-4 \{m,n\}至少m次,至多n次

[root@station47 ~]# grep --color "x\{1,2\}y" test1.txt
xxy
xy
xxy
[root@station47 ~]#


   注:这里,x最少出现一次,最多出现了2次


   2-5 \{m,\}至少m次


[root@station47 ~]# grep --color "x\{1\}y" test1.txt
xxy
xy
xxy
[root@station47 ~]#


    注:至少出现1次,因此y那一行由于是0次没有显示出来


   2-6 \{0,n\}至多n次


[root@station47 ~]# grep --color "x\{2\}y" test1.txt
xxy
xxy
[root@station47 ~]#


     注:最多出现2次x


   3.位置锚定


   位置锚定是通过一定的格式,将一些字符或者字符串固定在想要的位置上。


^锚定行首
$
锚定行尾
^$
空白行
\<锚定词首
\>锚定词尾

   演示用文本


xxy
xy
y
xxy
axyxyb
abc


   3-1 ^ 锚定词首。显示以root开头的行。


[root@station47 ~]# grep --color "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@station47 ~]#

   注:以root为行首的行

    3-2 $ 锚定词尾。显示以bash为词尾的行


[root@station47 ~]# grep --color "bash$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
Root:x:500:500::/home/Root:/bin/bash
testuser:x:501:501::/home/testuser:/bin/bash
user1:x:502:502::/home/user1:/bin/bash
Badguy:x:503:503::/home/Badguy:/bin/bash
Creayboy:x:504:504::/home/Creayboy:/bin/bash
[root@station47 ~]#

   3-3 ^$ 不显示空白行。


[root@station47 ~]# grep --color -v "^$" test1.txt
xxy
xy
y
xxy
abc
[root@station47 ~]#


    注:此处使用了反向显示。


   3-4 \<锚定词首


[root@station47 ~]# grep --color=auto "\<xy" test1.txt
xy
[root@station47 ~]#


    若不锚定词首,则会出现下面的结果


[root@station47 ~]# grep --color=auto "xy" test1.txt
xxy
xy
xxy
axyxyb
[root@station47 ~]#

    3-5 锚定词尾


[root@station47 ~]# grep --color=auto "xy\>" test1.txt
xxy
xy
xxy
[root@station47 ~]#


     若不锚定词尾


[root@station47 ~]# grep --color=auto "xy" test1.txt
xxy
xy
xxy
axyxyb
[root@station47 ~]#


   4.分组显示


\(\)eg:\(ab)\*xy

   如上实例,将ab做为一个分组,以组合的形式出现。在下面的引用中,做实例


   5.引用


\1后向引用。eg:\(a.b\)xy\1可以匹配到a6bxya6b
\2 多次后向引用,后面的数字可增大


   示例用文本


#test2.txt
He like his lover.
She love her liker.
He love his lover.
She like her liker.



   找出like对应liker,love对应lover的行


[root@station47 ~]# grep --color=auto "\(l..e\).*\1r" test2.txt
    He love his lover
    She like her liker
[root@station47 ~]#

   注:这里,使用了后向引用和分组。将l..e固定为一个组,然后后向引用。


五、匹配模式之扩展正则表达式


   扩展正则表达式与基本正则表达式十分相似,二者最主要的区别就是扩展正则表达式不使用转义字符。下面是二者元字符的对比表


字符匹配
基本正则表达式扩展正则表达式说明

..
任意单个字符

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

[^][^]
指定范围外的任意单个字符
次数匹配基本正则表达式扩展正则表达式说明

**匹配其前面的字符任意次

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

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

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

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

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

----+匹配其前面的字符至少1次
位置锚定基本正则表达式扩展正则表达式说明

^^锚定行首

$$锚定行尾

\<, \b\<, \b锚定词首

\>, \b\>, \b锚定词尾


分组基本正则表达式扩展正则表达式说明

\(\)()分组

扩展正则表达式与基本正则表达式类似,因此不再给出示例。


六、结语


   grep是文本搜索的利器,是后续学习Linux的基础,因此不紧要掌握基本的内容,更好熟练的使用。写完这篇博客,回头再看,想说爱它,我想,可以开口了。

   注:本文是小菜鸟的第一篇,中间定会有一些错误、遗漏和不足。欢迎各位批评指正,积极留言。根据大家的执教,不定期迭代更新。



   Version:1.0: 2014-2-24

   Version:1.1: 2014-2-26,更新表格样式,修改部分错别字。建议51cto博客编辑器更加人性化,对表格支持、预览功能做更多的优化。