如何在文件中搜索多行模式?

Oli*_*Oli 113 linux command-line grep find pcregrep

我需要找到包含特定字符串模式的所有文件.想到的第一个解决方案是使用带有xargs grep的find管道:

find . -iname '*.py' | xargs grep -e 'YOUR_PATTERN'
Run Code Online (Sandbox Code Playgroud)

但是如果我需要找到跨越多行的模式,我就会被卡住,因为vanilla grep找不到多行模式.

Oli*_*Oli 93

所以我发现pcregrep代表Perl兼容的正则表达式GREP.

例如,您需要查找" _name "变量后面紧跟" _description "变量的文件:

find . -iname '*.py' | xargs pcregrep -M '_name.*\n.*_description'
Run Code Online (Sandbox Code Playgroud)

提示:您需要在模式中包含换行符.根据您的平台,它可能是'\n',\ r','\ r \n',...

  • 正如下面的halka所提到的,"如果你将(?s)添加到正则表达式中,你也可以说服点通配符匹配换行符".然后通过添加-P将grep与perl正则表达式一起使用.找 .-exec grep -nHP'(?s)SELECT.{1,60} FROM.{1,20} table_name''{}'\; (7认同)
  • `pcregrep`可以在mac上使用`brew install pcre` (7认同)

小智 87

你为什么不去找awk:

awk '/Start pattern/,/End pattern/' filename
Run Code Online (Sandbox Code Playgroud)

  • 太好了!有没有办法使这场比赛不贪婪? (20认同)
  • 你怎么只在匹配时打印文件名? (3认同)
  • 这很容易理解,并使用大多数* nix系统随附的`awk`。 (2认同)
  • 你可以用'awk'/ Start pattern /,/ End pattern/{printf NR""来显示匹配的行号.print}'filename`.你可以通过给行号固定宽度来使它更漂亮:`awk'/ Start pattern /,/ End pattern/{printf"%-4s",NR; print}'filename`. (2认同)

aya*_*yaz 71

以下是使用GNUgrep的示例:

grep -Pzo '_name.*\n.*_description'
Run Code Online (Sandbox Code Playgroud)

-z/ --null-data将输入和输出数据视为行序列.

另见这里

  • 对于非ASCII文件,我建议''**grep -Pazo**''而不是''-Pzo''.这是更好的,因为-z开关非ASCII文件**可能会触发grep的"二进制数据"行为,这会改变返回值.切换'' - a | --text''阻止了. (4认同)
  • 我认为这仅占一个换行符。 (2认同)

buk*_*zor 21

grep -P还采用libpcre,但很多更广泛安装.要查找titlehtml文档的完整部分,即使它跨越多行,您也可以使用:

grep -P '(?s)<title>.*</title>' example.html
Run Code Online (Sandbox Code Playgroud)

由于PCRE项目实现了perl标准,因此请使用perl文档作为参考:


Oli*_*Oli 15

这是一个更有用的例子:

pcregrep -Mi "<title>(.*\n){0,5}</title>" afile.html
Run Code Online (Sandbox Code Playgroud)

它在html文件中搜索title标签,即使它最多可以跨越5行.

以下是无限行的示例:

pcregrep -Mi "(?s)<title>.*</title>" example.html 
Run Code Online (Sandbox Code Playgroud)

  • @matt:如果你在你的正则表达式中添加`(?s)`,你也可以说服点通配符匹配换行符:`"(?s)<html>.*</ html>"` (7认同)
  • 谢谢你.我没有意识到通配符与换行符不匹配. (4认同)

Shw*_*ogg 8

随着银搜索:

ag 'abc.*(\n|.)*efg'
Run Code Online (Sandbox Code Playgroud)

银色搜索者的速度优化可能会在这里发挥作用.


alb*_*fan 5

这个答案可能有用:

需要用于多行搜索的正则表达式(grep)

要递归查找,您可以使用标志 -R (递归)和 --include (GLOB 模式)。看:

使用 grep --exclude/--include 语法不通过某些文件进行 grep


小智 5

@Marcin:awk 非贪婪示例:

awk '{if ($0 ~ /Start pattern/) {triggered=1;}if (triggered) {print; if ($0 ~ /End pattern/) { exit;}}}' filename
Run Code Online (Sandbox Code Playgroud)