grep 命令指北
在上周的 shell 分享中,涛哥给我们展示了 grep 强大的文本搜索能力。鉴于自己对这一功能的不熟悉,于是利用周末时间赶紧补习。
grep 命令用于从给定的多行数据中筛选出匹配的行。常用的 egrep 是 grep -E 的 alias,fgrep 是 grep -F 的 alias。下面我以 man grep 中的解释以及自己的一些操作来说明其主要 S 操作。
定义:grep [OPTIONS] PATTERN [FILE…]
grep [OPTIONS] [-e PATTERN]… [-f FILE]… [FILE…]
grep 从 FILES 中查找匹配给定 PATTERN 的行。如果没有 file 指定,或者是用中划线 - ,grep 会从标准输入中查找。默认 grep 会输出匹配到的行。同时上面说到的 egrep 和 fgrep 都是被弃用了的,只是考虑到后向兼容而提供的。
参数:
1 2 3 4 5 6 7 8 9 10
| 通用程序信息: --help 显示帮助信息 -V, --version 显示grep的版本,然后退出
匹配模式选择: -E, --extended-regexp 解释PATTERN为扩展正则表达式(ERE) -F,--fixed-strings 解释PATTERN为一串固定的字符串(而不是正则表达式了),用换行符分个,每一个都会被匹配到 -G,--basic-regexp 解释PATTERN为基础正则表达式(BRE)。介个是默认的正则。 -P,--perl-regexp 解释PATTERN为Perl兼容的正则表达式(PCRE)。这是个实验属性。(为啥没有javascript兼容的)
|
举个 - F 的比方:
这里使用 - F,输入完第一个要匹配的后,回车,继续输入,输入完成后,输入表示结束的单引号。
1 2 3 4 5 6 7
| 匹配控制: -e PATTERN, --regexp=PATTERN 使用PATTERN。如果被使用多次或者与-f结合使用,则会查所有pattern -f FILE, --file=FILE 从FILE文件获取PATTERN(每个PATTERN为一行)。如果被多次使用或者与-e结合,则查所有pattern -i, --ignore-case 忽略大小写 -v, --invert-match 输出不匹配的行 -w, --word-regexp 只选择匹配了PATTERN并且匹配到的单词必须是独立的单词。啥意思呢?就是说匹配到的行中该word的前后不能是字母、数字、下划线。下面打个例子。 -x,--line-regexp 只匹配 那些内容完全匹配PATTERN的行。有点相当于给PATTERN的前后加了个^$
|
瞅一下,默认情况下,只要你这行有这些连续的字符串,就匹配。然后看加了 - w 的:
看吧,加了 - w 的,最后一个 my_name1 并没有被匹配上,因为它不是一个独立的单词(前有下划线,后有数字,可怕)。
1 2 3 4 5 6 7 8 9
| 通用输出控制: -c,--count 不输出匹配的行,而是输出匹配的行的数量。结合-v指令,输出不匹配的行数量 --color=WHEN,--colour=WHEN 对匹配的字符串进行终端着色。when可以是never、always、auto -L,--files-withour-match 不输出匹配的行,而是输出没有任何匹配的文件的名称。对每个文件的扫描会在有第一次匹配时终止。 -l,--files-with-matches 对-L的取反,输出存在匹配内容的文件的名称。同样会在第一次匹配到时终止哟。 -m NUM,--max-count=NUM 在一个文件匹配到NUM个行时停止读取文件。在输出NUM行匹配的行后,会吐出一个上下文。这个上下文就是最后一次成功匹配的那一行的位置。这个东西下面讲-A,-B,-C的时候有用哦。尽请期待思密达。如果配合-v,则会输出NUM个不匹配的行。 -o,--only-matching 只打印匹配行中的匹配部分(非空) -q,--quiet,--silent 不打印任何东西。如果有匹配,那么以状态0退出,如果没有匹配,则非零退出。 -s,--no-message 禁止错误信息输出到标准输出流。文件可能不存在或者不可读。
|
1 2 3 4 5 6 7 8 9
| 输出行前缀的控制: -b,--byte-offset 输出该行到文件头(从零开始)的字节偏移。如果指定了-o,则偏移量为匹配到的字符串的偏移量 -H,--with-filename 输出每一行匹配到的行的文件来源。当超过了一个文件时,默认开启此命令。 -h,--no-filename 不输出。。。当只有一个文件,默认开启。。。 --label=LABEL 指定grep的输入流的标签。比如 gzip -cd foo.gz | grep --label=foo -H something理解为gzip输出流pipe给grep,grep接收数据以label为依据。 -n,--line-number 从1开始,输出匹配到的行在整个文件中的第几行 -T,--initail-tab 对于-H,-b,-n的指令,将其前缀放在一个tab的中间显示。 -u,--unix-byte-offsets 报告unix风格的字节偏移量 -Z,--null 如果输出的是文件名,则将各个文件名之间的换行符去掉
|
1 2 3 4 5
| 上下文行控制: -A NUM,--after-context=NUM 打印由-m指定的最后一次匹配的行的后NUM行。每个分组之间以两个中划线‘- -’分割 -B NUM,--before-context=NUM 打印由-m指定的最后一次匹配的行的前NUM行。分割。。 -A NUM,--context=NUM 打印由-m指定的最后一次匹配的行的前后NUM行。分割。。 上面三个,在指定了-o指令时不生效,并会产生警告。
|
举个例子:
由上图,指定了 - m 为 2,即匹配两次 sb。然后吐出第 1、9 行的位置。-A 会从第 1、9 行开始读取下面两行,打印出来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 文件和目录选择: -a,--text 把一个二进制文件当作文本来处理。等同于--binary-files=text --binary-files=TYPE 比较复杂,不忙说。 -D ACTION,--devices=ACTION -d ACTION,--directories=ACTION --exclude=GLOB --exclude-from=FILE --exclude-dir=DIR -I --include=GLOB -r, --recursive 递归所有目录下的文件,如果在命令行中指定了软链接,才会去递归。等于-d recurse -R,--dereference-recursive 在-r的基础上,除去了必须在命令行中指定软链接
其它选项: --line-buffered 使用行缓存。可能有性能问题。 -U,--binary 把文件当作二进制数据。主要针对MS-DOS和MS-Windos来说,指定了这个,将不会默认开启对CR的清除。在其他平台上无效。 -z,--null-data 输入流的每行数据不以换行符为分割,而是以NUL字符为分割。
|
关于一点其他的骚操作:
取出关键字,剔除其它:
grep PATTERN -oP file
-o 是仅输出匹配部分,-P 是使用 Perl 正则(grep 中只有这个可以使用零宽断言)