假设我们正在对一堆文件进行多行正则表达式模式搜索,并且我们想要从 grep 中提取匹配项。默认情况下,grep 输出由换行符分隔的匹配项,但由于我们正在执行多行模式,这会造成我们无法轻松提取单个匹配项的不便。
grep -rzPIho '}\n\n\w\w\b' | od -a
根据文件树中的文件,这可能会产生类似的输出
0000000 } nl nl m y nl } nl nl i f nl } nl nl m
0000020 y nl } nl nl m y nl } nl nl i f nl } nl
0000040 nl m y nl
0000044
如您所见,我们无法分割换行符来获取匹配项以供进一步处理,因为匹配项本身包含换行符。
现在
--null
(或 -Z
)只能与 -l
一起使用,这使得 grep 只列出文件名而不是匹配项,所以这在这里没有帮助。
注意,这不是 Find 的 -print0 和 xargs 的 -0 开关有等效的 grep 吗?,因为该问题的要求不同,允许使用替代技术来回答。
那么,我们怎样才能做到这一点呢?也许将 grep 与其他工具结合使用?
因此,我将此问题作为功能请求提交到 GNU grep bug 邮件列表中,它似乎是代码中的一个错误。
它已被修复并推送到master,因此它将在GNU grep的下一个版本中可用:http://git.savannah.gnu.org/cgit/grep.git/commit/?id=cce2fd5520bba35cf9b264de2f1b6131304f19d2
总结一下:此补丁确保
-z
标志不仅可以与 -l
一起使用,还可以与 -o
一起使用。
我想到的是使用组分隔符,例如:
grep -rzPIho '}\n\n\w\w\b' $FILE -H | sed "s/^$FILE:/\x0/"
这是另一种方法,它应该比 @bufh 发布的更简单,但也更复杂和更慢。
$ grep -rIZl '' --include='*.pl'| xargs -0 cat | dos2unix | tr '\n\0' '\0\n' \
| grep -Pao '}\x00\x00\w\w\b' | tr '\0\n' '\n\0' | od -a
显然只有在使用 Windows 行结尾时才需要 dos2unix。所以这里的要点是,我们将输入中的空字节与换行符交换,对空字节进行 grep 匹配,然后将内容交换回来。
0000000 } nl nl m y nul } nl nl i f nul } nl nl m
0000020 y nul } nl nl m y nul } nl nl i f nul } nl
0000040 nl m y nul
0000044
最新版本的 GNU grep 源现在可以使用 -z/--null 用空字符分隔输出,而以前它只能与 -l 结合使用:
http://git.savannah.gnu.org/cgit/grep.git/commit/?id=cce2fd5520bba35cf9b264de2f1b6131304f19d2
这意味着使用最新版本时您的问题会自动解决。