4

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

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

那么,我们怎样才能做到这一点呢?也许将 grep 与其他工具结合使用?

4

3 回答 3

5

所以我将此问题作为功能请求提交到 GNU grep 错误邮件列表中,它似乎是代码中的错误。

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

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

于 2016-03-18T17:04:32.403 回答
1

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

grep -rzPIho '}\n\n\w\w\b' $FILE -H | sed "s/^$FILE:/\x0/"
于 2016-03-18T10:07:58.940 回答
1

这是执行此操作的另一种方法,它应该比@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

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
于 2016-03-18T12:17:30.360 回答