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命令参数太多,我也是查的次数太频繁,某些高级参数用到时经常有点模糊才总结了这篇文章。