Linux命令详解 - grep

Linux命令详解 - grep

按照我们以前学习Linux命令的套路,我们习惯于先man一下,看下系统怎么解释这个命令。详细的文档参考这里:http://www.gnu.org/software/grep/manual/grep.html

系统的解释:

grep, egrep, fgrep - print lines matching a pattern

这个解释还是比较明晰的,打印匹配给定模式的行数

这里先提一下,上面提到了egrep、fgrep,这两个grep命令是由于历史的原因还依然存在,egrep=grep -E,fgrep=grep -F实际上是已经废弃了的命令,不再推荐使用

 

grep命令及其强大,按照参数控制的不同,分为几个方面:

Matcher Selection:匹配模式选择
Matching Control:匹配控制
General Output Control:通用输出控制
Output Line Prefix Control:输出内容控制
Context Line Control:内容输出行控制
File and Directory Selection:文件、目录选择
Other Options:其它选项

我们按照grep的各个方面来学习一下grep命令。

 

先看下Matcher Selection,选择合适的匹配器,grep支持四种匹配匹配选择:

-E:Extended Regular Expression,扩展正则
-F:Fixed String:固定的String模式
-G:Basic Regular Pattern:基本模式,默认
-P:Perl regular expression:支持Perl匹配

 

 选择合适的匹配模式,就可以按照选择方式进行匹配了。

关于Matching Control,grep支持下面几个参数控制:

 

   -e:PATTERN,支持使用-e参数,将PATTERN作为匹配的内容,PATTERN支持多个匹配内容
   -f:FILE,匹配模式从内容读取,每行一个匹配模式,如果文件为空的话,会匹配不出结果
   -i:这个最常见,表示匹配时不区分大小写
   -w:表示单词匹配,必须是单个词匹配上才算
   -x:这个表示是行匹配,必须是正行匹配上PATTERN才算
   -y:意义和-i一致,不过已经废弃了。

 

下面看下General Output Control,这个是控制输出的结果,实际上就是控制输出的一些内容:

 

   -c:这个参数会把其它的输出给去除,只剩下匹配的行数,如果添加-v参数,会输出没有匹配的行数
   -L:这个参数比较拗口,是输出没有匹配出内容的文件,换句话说,如果文件中有PATTERN符合要求,就不会输出文件名;另外值得一提的是,这个匹配只要匹配到首个符合PATTERN的内容就结束,不会继续进行。
   -l:和-L相反
   -m:NUM,控制最大匹配的行数NUM,grep能够控制最大输出不超过NUM行,加上-v参数的话,会输出最大NUM的非匹配行,如果是-c参数呢?读者可以自行学习下。
   -o:打印非空匹配部分,注意是只打印匹配的内容,不会打印整行内容
   -q:quiet,不打印任何内容,如果匹配找到立即返回0,即使有错误的话,也会立即返回
   -s:对于nonexistent和unreadable错误不会打印错误信息;注意该参数是在grep版本表现不一样,尤其要区别GNU版本和Unix版本的区别

 

上面的General Output Control是控制通用的输出,其实就是一些比较常见的输出控制,下面这个Output Line Prefix Control控制更为详细的信息,算是比较高级的内容。

   -b:打印byte偏移量输出,匹配的没个结果相对于文件开头的byte偏移。
   -H:打印匹配的每行的文件名,当有多个文件查找时这个是默认配置。
   -h:不会打印匹配的所在文件名,这个在单个文件查找时是默认配置
   -n:打印行数
   -T:
   -u:Unix-Style byte偏移量,将查找作为Unix style grep,最简单的例子就是CRLF等字符;如果有-b参数的话,-u参数不管用,另外-u参数只在windows情况下有效。
   -Z:会在输出的文件名之后输出一个Zero byte,而不是默认的:,这个参数比较让人困惑,不用也罢。

 

上面的Output Line Prefix Control控制信息也比较易于理解, 就是控制的一些输出控制;如果想对匹配的PATTERN信息控制,看下Context Line Control,这个控制信息是控制匹配行之后的输出信息

   -A:NUM,打印匹配行之后的NUM行信息;
   -B:NUM,打印匹配行之前的NUM行信息;
   -C:NUM,打印出包括匹配航在内的NUM行输出,--分割匹配一组匹配结果

 这组Output Line Prefix Control参数还是比较好用的。

 

File and Directory Selection这组参数是控制文件选择的,直接看下面的参数吧.

   -a:将二进制文件看做是text文件,相当于--binary-files=text的情况
   binary-files=TYPE:TYPE的值可以为binary、without-match、text,默认是binary;如果使用text的话,可能会有乱码输出
   -D:ACTION,输入可以为Device、FIFO、Socket等,使用该参数去处理这些输入;如果ACTION=read,这些输入源就好像和普通文件一样,如果ACTION=skip,不处理这些输入源。
   --exclude=glob:跳过符合glob匹配的文件,其中glob可以使用匹配符
   --exclude-from=file:这个是讲glob的内容放在file中,跳过符合这些匹配符匹配的文件。
   --exclude-dir=dir:跳过dir目录内容匹配。
   -I:相当于--binary-files=without-match
   --include=glob:指搜索符合glob匹配的文件,当然glob也可以使用匹配符
   -r:迭代处理目录下的文件,软连接会被跳过
   -R:跟-r参数一致,不过会处理软连接下的内容

 

除去上面的这些内容,还有一些Other Options可供选择

   --line-buffered:匹配输出buffered,有可能会引起性能问题
   --mmap:强制系统使用mmap读取文件,替代系统命令read读取,不过在现在系统下,mmap能够获得的性能提升有限,还有可能会引起潜在的问题:如IO Error、读取时文件内容变化等

 

提到grep的另外一个强大之处就是对于正则的支持,归于正则表达式大家想必都不陌生,这里只是简单提一下,仅供以后参考:

下面这些正则内容,grep都支持:

   *      The preceding item will be matched zero or more times.
   +      The preceding item will be matched one or more times.
   {n}    The preceding item is matched exactly n times.
   {n,}   The preceding item is matched n or more times.
   {,m}   The preceding item is matched at most m times.
   {n,m}  The preceding item is matched at least n times, but not more than m times.

如果想匹配?*.+{}[]()这些字符,请用反斜杠转义。

 

说到了反斜杠,还要提一下正则表达式中的Backslash Expression,这个是我们在写正则时最常用的表达式:

   \b:字符边界表示,这个表达式会将匹配的结果看做一个单词,而不会在单词中匹配结果
   \B:字符非边界表示,匹配必须出现在单词中
   \w:匹配所有的[a-zA-Z_0-9]
   \W:非\w
   \s:匹配空白字符
   \S:非\s

 注意,grep还支持这两个匹配字符\<和\> 转义,这两个也是匹配字符边界的,我看官方文档和\b没有区别,只是\b单个就能表达前后边界,而\<表示字符前面的边界,\>表示字符后面的边界。

 

另外grep还预定义了一些括号表达式,这些 grep预定义的表达式和常规的正则表达式意义一样,只是内容更丰富、控制更加细致;常用的又这些:

   [:alnum:]:[:alpha:]和[:digit:]的字符集合
   [:alpha:]:[:lower:]和[:upper:]的字符集合,[a-zA-Z]
   [:blank:]:Space和Tab键
   [:cntrl:]:ASCII表中从000到037的字符,再加上177(DEL),注意是八进制
   [:digit:]:数字,[0-9]
   [:graph:]:[:alnum:]和[:punct:]的字符集合
   [:lower:]:[a-z],小写字母
   [:print:]:可打印字符,[:alnum:]和[:punct:]的字符集合
   [:punct:]:符号字符,都有!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
   [:space:]:CRLF、Tab等不可见字符
   [:upper:]:[A-Z],大写字母
   [:xdigit:]:Hexadecimal digit,[0-9a-fA-F],十六进制数
   

 大家对比下上面两个内容,看看正则表达式的BackSlash Expression和grep的预定义表达式的区别。

 

 

grep命令非常的强大,能帮助我们做很多事;尤其在处理日志、查询内容,完成正常工作内容时。所以努力学习grep,加上以前的sort、uniq,处理日志就是一把瑞士军刀,无往不胜。

哈哈,瑞士军刀有点过了,不过处理日常工作绰绰有余;grep命令参数太多,我也是查的次数太频繁,某些高级参数用到时经常有点模糊才总结了这篇文章。

 

 

相关推荐