如何让grep通过NULL字符单独输出?

How to make grep separate output by NULL characters?

假设我们正在对一堆文件进行多行正则表达式模式搜索,并且我们想从 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 只列出文件名而不是匹配项,所以这对这里没有帮助。

请注意,这不是 Is there a grep equivalent for find's -print0 and xargs's -0 switches? 的重复,因为该问题的要求不同,因此可以使用替代技术来回答。

那么,我们怎样才能让它发挥作用呢?也许将 grep 与其他工具结合使用?

我想到的是使用组分隔符,例如:

grep -rzPIho '}\n\n\w\w\b' $FILE -H | sed "s/^$FILE:/\x0/"

这是另一种方法,它应该比@bufh 发布的更简单,但也更复杂、更慢。

$ grep -rIZl '' --include='*.pl'| xargs -0 cat | dos2unix | tr '\n[=10=]' '[=10=]\n' \
      | grep -Pao '}\x00\x00\w\w\b' | tr '[=10=]\n' '\n[=10=]' | od -a

dos2unix 显然只有在使用 windows 行尾时才需要。所以这里的重点是我们用输入中的换行符交换空字节,而不是在空字节上进行 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 错误邮件列表中将此问题作为功能请求提交,它似乎是代码中的错误。

它已被修复并推送到 master,因此它将在下一个 GNU grep 版本中可用:http://git.savannah.gnu.org/cgit/grep.git/commit/?id=cce2fd5520bba35cf9b264de2f1b6131304f19d2

总结一下:此补丁确保 -z 标志不仅与 -l 结合使用,而且与 -o.

结合使用