如何在多行上grep多个模式?
确切地说
Some text begin Some text goes here. end Some more text
我想提取从“开始”到“结束”的整个块。
使用awk,我们可以像awk '/begin/,/end/' text
。
grep怎么办?
更新于2016年11月18日 (因为grep行为已更改:grep with -P参数现在不支持^
和$
anchors [在Ubuntu 16.04上使用内核v:4.4.0-21-generic])( 错误(非)修复 )
$ grep -Pzo "begin(.|\n)*\nend" file begin Some text goes here. end
注意:对于其他命令,只需用新行锚'\n'
替换’^’和’$’锚点______________________________
使用grep命令:
grep -Pzo "^begin\$(.|\n)*^end$" file
如果您不希望在结果中包含“begin”和“end”模式,请将grep与Lookbehind和Lookahead支持一起使用。
grep -Pzo "(?<=^begin$\n)(.|\n)*(?=\n^end$)" file
您也可以使用\K
notify而不是Lookbehind断言。
grep -Pzo "^begin$\n\K(.|\n)*(?=\n^end$)" file
\K
选项在模式匹配之前忽略所有内容并忽略模式本身。
\n
用于避免从输出中打印空行。
或者@AvinashRaj建议有简单易用的grep如下:
grep -Pzo "(?s)^begin$.*?^end$" file grep -Pzo "^begin\$[\s\S]*?^end$" file
(?s)
告诉grep允许点匹配换行符。
[\s\S]
匹配任何空白或非空白字符。
它们的输出不包括“开始”和“结束”如下:
grep -Pzo "^begin$\n\K[\s\S]*?(?=\n^end$)" file # or grep -Pzo "(?<=^begin$\n)[\s\S]*?(?=\n^end$)" grep -Pzo "(?s)(?<=^begin$\n).*?(?=\n^end$)" file
请参阅此处所有命令的完整测试 ( 已更改为-p参数的grep行为已更改 )
注意:
^
指向一行的开头, $
指向一行的结尾。 这些添加到“开始”和“结束”的周围以匹配它们,如果它们在一条线上。
在两个命令中,我转义了$
因为它还用于“命令替换”( $(command)
),它允许输出命令来替换命令名。
从男人grep:
-o, --only-matching Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line. -P, --perl-regexp Interpret PATTERN as a Perl compatible regular expression (PCRE) -z, --null-data Treat the input as a set of lines, each terminated by a zero byte (the ASCII NUL character) instead of a newline. Like the -Z or --null option, this option can be used with commands like sort -z to process arbitrary file names.
如果你的grep
不支持perl语法( -P
),你可以尝试连接行,匹配模式,然后再次扩展行,如下所示:
$ tr '\n' , < foo.txt | grep -o "begin.*end" | tr , '\n' begin Some text goes here. end