GREP是Global search Regular Expression and Print out the line的简称,即全面搜索正则表达式
并把行打印出来。GREP是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打
印出来,grep也是Linux 中最广泛使用的命令之一。本节重点介绍grep命令,以及grep命令与正则表
达式结合使用.
grep命令是支持正则表达式的一个多用途文本搜索工具,grep的一般格式为:
grep [选项][模式][文件…]
grep命令由选项、模式和文件三部分组成,它在一个或多个文件中搜索满足模式的文本行,模式后的
所有字符串被看做文件名,文件名可以有多个,搜索的结果被打印到屏幕,不影响原文件的内容。gre
p命令的选项用于对搜索过程进行补充说明,grep命令的选项及其意义如下表所示。
grep命令选项及其意义
grep命令的模式十分灵活,可以是字符串,也可以是变量,还可以是正则表达式。需要说明的是,
无论模式是何种形式,只要模式中包含空格,就需要使用双引号将模式引起来,如果不加双引号,空
格后的单词容易被误认为是文件名,如普通字符串为"hello world",grephello world命令就将world
认为是文件名,因此,grep"hello world"filename才是正确的写法。大部分情况下,使用单引号将模
式引起来也是可以的;一旦模式中包含空格,就需要使用双引号或单引号将模式引起来。下面的例子
可以充分验证这个观点。
模式包含空格时,是否使用双引号的区别
#文件test内容 [shizhenning@zabbix ~]$ cat test job joob jooob joooob hello world! hello jimmy! #查询包含字符串"hello"的行,不需要""引用模式 [shizhenning@zabbix ~]$ grep hello test hello world! hello jimmy! #查询包含字符串"hello world"的行,不使用""引用模式时:提示找不到文件或#者目录world [shizhenning@zabbix ~]$ grep hello world test grep: world: 没有那个文件或目录 test:hello world! test:hello jimmy! #查询包含字符串"hello world"的行,使用""引用模式时:返回正确结果 [shizhenning@zabbix ~]$ grep "hello world" test hello world!
首先搜索test文件中包含 hello 字符串的行,由于模式 hello 中不包含空格,因此,是否用引号引
起模式对grep 命令不产生影响。当我们要搜索test 文件中包含hello world 字符串的行时,不用双
引号将hello world 括起来时,Shell 提示没有 world 这个文件或目录,然后,给出test 文件中包
含 hello world 字符串的行,这说明Shell将grep hello world test这条命令解释为在world和test
两个文件中搜索包含hello字符串的行,这显然与我们的初衷不符。而当我们用双引号将hello world
括起来后,就得到了正确的结果。
grep支持多文件查询,请看下面的例子。
演示grep 的多文件查询
#grep 多文件查询 [shizhenning@zabbix ~]$ grep jooob test test1 test:jooob test1:jooob #grep 多文件查询,不显示文件名 [shizhenning@zabbix ~]$ grep -h jooob test test1 jooob jooob
上例从 test和test1 两个文件中搜索包含 jooob 字符串的行,命令逐个给出待搜索的文件,结果打印出所有包含jooob字符串的行,默认以文件名开头,可以使用-h选项隐藏文件名
grep 常用选项介绍:
grep命令指定多个文件时可以使用通配,这样就不必逐个给出待搜索的文件了,例如
用通配表示多文件
[shizhenning@zabbix ~]$ grep -e "\<joob\>" test test1 test:joob test1:joob #可以修改为如下命令 [shizhenning@zabbix ~]$ grep -e "\<joob\>" test* test:joob test1:joob
上例利用test*代替了test 和test1 两个文件,显得十分简洁。
下面我们结合具体例子逐个说明grep选项的含义和用法。
1.-c 选项
-c选项表示输出匹配字符串行的数量,默认情况下,grep命令打印出包含模式的所有行,一旦加上-c选项,就只显示包含模式行的数量,下面给出一个使用-c选项的例子。
grep -c 的用法:
[shizhenning@zabbix ~]$ grep "j*b" test job joob jooob joooob #grep -c 用法,仅显示匹配模式的行数 [shizhenning@zabbix ~]$ grep -c "j*b" test 4
2.-n选项
-n选项列出所有的匹配行,并显示行号。默认情况下,grep搜索单个文件时,只显示每行的内容,搜索多个文件时,显示文件名及每行的内容,加上-n选项后,将在行内容前附加显示行号,下面给出一个使用-n选项的例子。
grep -n 的用法
[shizhenning@zabbix ~]$ grep "j*b" test* test:job test:joob test:jooob test:joooob test1:job test1:joob test1:jooob test1:joooob test1:jooooob #grep -n 选项使用,显示行号 [shizhenning@zabbix ~]$ grep -n "j*b" test* test:1:job test:2:joob test:3:jooob test:4:joooob test1:2:job test1:3:joob test1:4:jooob test1:5:joooob test1:6:jooooob
3.-v 选项
-v选项显示不包含模式的所有行,下面给出一个使用-v选项的例子。
grep -v 的用法:
[shizhenning@zabbix ~]$ grep -v "j*b" test* test:hello world! test:hello jimmy! test: test1:ignore test1: [shizhenning@zabbix ~]$ grep -vc "j*b" test* test:3 test1:2
结合使用-v 和-c 参数列出test、test1文件中不包含模式中的关键字的行数。
4.-i 选项
默认情况下,grep命令对大小写是敏感的,如果加上-i选项就表示grep命令不区分大小写,下面给出一个使用-i选项的例子。
grep -i 的用法
#不使用-i,区分大小写 [shizhenning@zabbix ~]$ grep "j*b" test* test:job test:joob test:jooob test:joooob test1:job test1:joob test1:jooob test1:joooob test1:jooooob #使用-i,不区分大小写 [shizhenning@zabbix ~]$ grep -i "j*b" test* test:job test:joob test:jooob test:joooob test1:job test1:joob test1:jooob test1:joooob test1:jooooob test1:JoooooB
5.-h选项
-h选项表示查询多文件时不显示文件名,默认情况下,grep命令查询多个文件时,在匹配行之前显示文件名,加上-h选项后,grep命令将不再显示文件名。下面给出一个使用-h选项的例子。
[shizhenning@zabbix ~]$ grep "j*b" test* test:job test:joob test:jooob test:joooob test1:job test1:joob test1:jooob test1:joooob test1:jooooob #使用-h选项,只显示行内容,不显示文件名 [shizhenning@zabbix ~]$ grep -h "j*b" test* job joob jooob joooob job joob jooob joooob jooooob
6.-l 选项
-l 选项表示只列出符合匹配的文件名,而不列出具体匹配行,下面给出一个使用-l 选项的例子。
grep -l 的用法
[shizhenning@zabbix ~]$ grep "Hello World" test test1 test:Hello World! #使用-l选项,只显示包含匹配模式的文件名 [shizhenning@zabbix ~]$ grep -l "Hello World" test test1 test
7.-s 选项
-s 选项表示不显示不存在或无匹配文本的错误信息,默认情况下,grep 在待搜索文件不存在或搜索不到符合模式的文本行时将打印错误信息。下面给出一个使用-s选项前后比较的例子
grep -s 的用法
[shizhenning@zabbix ~]$ grep "Hello World" test test1 test2 test:Hello World! grep: test2: 没有那个文件或目录 #使用-s选项,不显示错误信息 [shizhenning@zabbix ~]$ grep -s "Hello World" test test1 test2 test:Hello World!
给出同样的命令使用-s 选项前后的结果,两条命令都在搜索Hello World字符串,当未使用-s 选项时,提示test2文件不存在的错误信息,但是,在grep后加上-s选项后,就不再打印错误信息了。
8.-r 选项
默认情况下,grep命令只对当前目录下的文件进行搜索,而不对子目录中的文件进行搜索。-r 选项表示递归搜索,不仅搜索当前目录,而且搜索子目录。下面举一个-r选项的例子。
grep -r 的用法
[shizhenning@zabbix ~]$ grep "hello" * test:hello world! test:hello jimmy! #使用-r选项进行递归查询 [shizhenning@zabbix ~]$ grep -r "hello" * aaa/aaa1:hello world! test:hello world! test:hello jimmy!
对当前目录递归搜索hello 字符串,不仅列出当前目录下文件的搜索结果,还列出了子目录aaa 下文件包含hello字符串的文本行。
9.-w 和-x 选项
grep命令的模式是支持正则表达式的,正则表达式的元字符将被解释成特殊的含义,-w选项表示匹配
整词,即以模式的字面含义去解析它。因此,grep命令使用-w选项后,元字符不再被解释为特殊含
义,下面的例子说明了-w项
grep -w 的用法
#grep -w 的用法 [shizhenning@zabbix ~]$ grep hel* test* test:hello world! test:hello jimmy! #加上-w选项后,表示搜索包含hel*字符串的文本行 [shizhenning@zabbix ~]$ grep -w hel* test* [shizhenning@zabbix ~]$#没有满足该条件的文本行
上例两条命令的模式都为hel*,当未用-w 选项时,模式中的*被解析为任意字符,即搜索包含以
cer 开头字符串的文本行;加上-w选项后,*被解析为字面含义,表示搜索包含cer*字符串的文本行,
当前目录中的文件中不包含cer*这一完整的字符串。因此,无任何结果输出。
-x 选项是匹配整行,即只有当文件中有整行内容与模式匹配时,grep命令才输出该行结果,下面的例
子说明grep命令的-w和-x 选项的区别。
说明grep 命令的-w和-x 选项的区别
[shizhenning@zabbix ~]$ cat test #查看文件test内容 job joob jooob joooob jimmy hello hello world! hello jimmy! Hello World! #搜索包含单词jimmy的问本行 [shizhenning@zabbix ~]$ grep -w 'jimmy' test jimmy hello jimmy! #搜索正行文本是单词jimmy的行 [shizhenning@zabbix ~]$ grep -x 'jimmy' test jimmy
可以看出,-w 选项搜索的是整词匹配,而-x 选项搜索的是整行匹配。
10.-q 选项
从上面的讲解中知道,grep命令默认情况下是输出结果的,但是,grep命令后一旦加上-q 选项,grep
将不再输出任何结果,而是以退出状态表示搜索是否成功,退出状态0 表示搜索成功,退出状态1 表
示未搜索到满足模式的文本行,退出状态2表示命令或程序由于错误而未能执行。
下面我们举一个例子说明grep -q 选项的含义。
演示grep -q 选项
#grep命令搜索成功 [shizhenning@zabbix ~]$ grep -qx 'jimmy' test [shizhenning@zabbix ~]$ echo $? 0 #退出状态为0 #grep命令未搜索到匹配模式的文本行 [shizhenning@zabbix ~]$ grep -qx 'jimmy' test1 [shizhenning@zabbix ~]$ echo $? 1 #退出状态为1 #grep命令执行失败 [shizhenning@zabbix ~]$ grep -qx 'jimmy' test2 grep: test2: 没有那个文件或目录 [shizhenning@zabbix ~]$ echo $? 2 #退出状态为2
grep命令的-E 和-F选项分别等价于grep命令族中的egrep和fgrep命令。有关grep 命令选项、模式和文件的介绍到此为止。
grep和正则表达式结合使用
将带元字符的正则表达式用于grep命令能够更灵活地匹配信息,使用时需要使用单引号将正则表达式
引起来,以免发生一些不可预知的错误。下面通过一些例子来介绍grep与正则表达式结合的用法,以
加强读者对grep命令的认识,而且有利于对正则表达式的巩固。
1.匹配行首
元字符"^"表示行首,若需要匹配.pem为后缀文件中以横杠(-)开头的行,可输入如下所示的命令:
grep 查找以h符号开头的行
[shizhenning@zabbix ~]$ cat test job joob jooob joooob jimmy hello hello world! hello jimmy! Hello World! #查找以h字符开头的问本行 [shizhenning@zabbix ~]$ grep '^h' test hello hello world! hello jimmy! [shizhenning@zabbix ~]$
下面的例子结合grep和正则表达式搜索空白行,第1 个命令的意义为匹配test文件中空白行的行数,显示结果说明test文件中有1行空白行。第2 个命令为匹配test文件中非空白行的行数,此时使用[^$]符号表示空白行范围,前面加上"^"符号取反,显然,^^$表达式是错误的,因为grep 将第1 个"^"理解为行首,显示结果说明test文件中有27 行空白行。
查找空白行
#查找空白行,只打印行数 [shizhenning@zabbix ~]$ grep -c '^$' test 1 #查找飞空白行,只打印行数 [shizhenning@zabbix ~]$ grep -c '^[^$]' test 9
2.设置大小写
利用-i 符号可以使grep 命令不区分大小写,当然也可利用[]符号来实现这一功能。下面给出用[]符号设置大小写的例子。
用[]符号设置大小写
[shizhenning@zabbix ~]$ grep -n '[Hh]ello' test 6:hello 7:hello world! 8:hello jimmy! 9:Hello World!
上例匹配test文件中Hello和hello两个关键字的行,并使用-n显示匹配的行号。
3.匹配重复字符
匹配重复字符通常可以利用"."符号和"*"符号来实现。首先举一个"."符号的例子。
grep 和.符号
[shizhenning@zabbix ~]$ cat test job joob jooob joooob jimmy hello hello world! hello jimmy! Hello World! /usr/local/zabbix/ /home/shizhenning/ [shizhenning@zabbix ~]$ grep '^/.../' test /usr/local/zabbix/
上例搜索test文件中以/字符开始、中间3个任意字符、第5个字符仍为/的行,显示结果/usr/满足匹配条件。
然后给出一个"*"符号的例子。
grep 和*符号
[shizhenning@zabbix ~]$ grep '^/.*/' test /usr/local/zabbix/ /home/shizhenning/
上例搜索以"/"开头,后面跟一个任意字符,可以重复0次或者多次,后面仍是"/"字符的行。
4.转义符
如果匹配的目标字符串中包含元字符,则需要利用转义符"\"屏蔽其意义。如果需要搜索包含
aa.bb.cc字符串的行,由于句号"."字符是元字符,所以,需要在"."符号之前加上"\"符号进行转
义。如果将命令写成
grep 'aa.bb.cc' test
则是匹配aa 和bb、cc 之间存在任意单个字符的行,如aaxbbxcc 能够满足条件。下面给出
搜索包含aa.bb.cc字符串的行的例子。
grep 和转义符
[shizhenning@zabbix ~]$ cat test job joob jooob joooob jimmy hello hello world! hello jimmy! Hello World! /usr/local/zabbix/ /home/shizhenning/ aa.bb.cc [shizhenning@zabbix ~]$ grep -n 'aa\.bb\.cc' test 12:aa.bb.cc [shizhenning@zabbix ~]$
由上例的结果可以看出,转义符使得元字符"."符号被解析为字面含义,打印出了包含aa.bb.cc字符串
的行。
横杠(-)字符较为特别,它虽然不属于正则表达式元字符,但是,由于"-"字符是引出grep 命令选项
的特殊字符,所以,当模式以"-"符号开头时,需要用转义符将其转义,请看下面的例子。
-字符在grep命令中的特殊性
[shizhenning@zabbix ~]$ cat test job joob jooob joooob jimmy hello hello world! hello jimmy! Hello World! /usr/local/zabbix/ /home/shizhenning/ aa.bb.cc ---comment--- [shizhenning@zabbix ~]$ grep '-\{3\}' test #模式以-符号开头 grep:无效选项 -- \ #提示错误,grep将模式解析为选项 Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more information. [shizhenning@zabbix ~]$ grep '\-\{3\}' test #使用转义符对-符号进行转义,返回正确结果 ---comment--- [shizhenning@zabbix ~]$
上面的命令在"-"符号前加上转义符,并用引号将模式引起来,得到了正确的结果。注意,这里模式上
的引号十分重要,如果不加引号,仍然提示无效选项错误。
#模式不加引号仍然提示错误 [shizhenning@zabbix ~]$ grep \-\{3\} test grep:无效选项 -- { Usage: grep [OPTION]... PATTERN [FILE]... Try `grep --help' for more information. [shizhenning@zabbix ~]$
5.POSIX字符类
为了保持不同国家的字符编码的一致性,POSIX(Portable Operating System Interface)增加了特
殊的字符类,以[:classname:]的格式给出,grep 命令支持POSIX 字符类,首先将POSIX类及其意义列
出。
POSIX字符类
下面举几个例子来说明POSIX 字符类的用法,首先,给出一个利用POSIX 字符类搜索以大写字母开头的行:
利用POSIX 字符类搜索以大写字母开头的行
[shizhenning@zabbix ~]$ grep '^[[:upper:]]' test Hello World!
上例的命令使用POSIX 字符类作为模式,[:upper:]表示大写字母集合,再用一层方括号将[:upper:]
括起,表示匹配字符集合,得到的结果确实是所有以大写字母开头的文本行。再举一个搜索以空格开
头文本行的例子:
搜索以空格开头文本行
[shizhenning@zabbix ~]$ cat test job joob jooob joooob jimmy hello hello world! hello jimmy! Hello World! /usr/local/zabbix/ /home/shizhenning/ aa.bb.cc ---comment--- Hello World! [shizhenning@zabbix ~]$ grep '^[[:space:]]' test Hello World! [shizhenning@zabbix ~]$
上例的命令仍以POSIX 字符类作为模式,[:space:]用法与[:upper:]类似。事实上,POSIX字符类作为
模式的用法都类似,使用时只要注意用方括号将POSIX 字符类括起来即可。
6.精确匹配
"\<\>"符号用于精确匹配,在此结合grep命令对此符号进行介绍。
首先给出一个说明性的例子,我们结合例子阐释何为精确匹配,以及"\<\>"符号的用法,例子如下所示:
精确匹配
[shizhenning@zabbix ~]$ cat test job joob jooob joooob jimmy hello hello world! hello jimmy! Hello World! /usr/local/zabbix/ /home/shizhenning/ aa.bb.cc ---comment--- Hello World! hell #搜索包含hell字符串的文本行 [shizhenning@zabbix ~]$ grep 'hell' test hello #hello中包含hell字符串 hello world! hello jimmy! hell #精确匹配hell这个单词 [shizhenning@zabbix ~]$ grep '\<hell\>' test hell [shizhenning@zabbix ~]$
事实上,grep命令的-w选项也可用于精确匹配,下面的命令等价于上例的 grep '\<hell\>' test 命令:
#使用-w选项来实现精确匹配 [shizhenning@zabbix ~]$ grep -w "hell" test hell
7.或字符
或字符"|"是扩展的正则表达式中定义的,grep需要加上-E选项才能支持它,下面给出grep命令使
用"|"字符的例子。
grep 命令与|字符
#使用-E选项grep执行成功 [shizhenning@zabbix ~]$ grep -E 'world|jimmy' test jimmy hello world! hello jimmy! #不适用-E选项没有找到匹配项 [shizhenning@zabbix ~]$ grep 'world|jimmy' test [shizhenning@zabbix ~]$ echo $? 1 #返回1,表示没有找到匹配模式的文本行 [shizhenning@zabbix ~]$
上诉两个命令用于匹配带有world或jimmy字符串的行,grep带上-E 选项后得到正确的结果。而grep没
有带-E 选项时,返回结果为空,这是因为grep命令将"|"字符解析为字面意义。注意,world|jimmy上
的引号必不可少。
grep命令与正则表达式结合使用极大地增加了命令应用的灵活性,同时也增大了使用命令的难度,只
有多练习,多思考分析,才有可能熟练而灵活地运用grep命令。