如何在多行上搜索多个模式?

Ike*_*ker 1 grep

准确地说

Some text
begin
Some text goes here.
end
Some more text
Run Code Online (Sandbox Code Playgroud)

我想提取从“开始”到“结束”的整个块

使用 awk 我们可以这样做

awk '/begin/,/end/' text
Run Code Online (Sandbox Code Playgroud)

怎么办grepgrep在某些 *nix 上是否有任何实现可以完成?

Sté*_*las 7

grepg/re/p是一个基本工具p RINT匹配的所有行ř egular ë上的表达。

更多在这里像你想小号tream ED itor:

sed '/^begin$/,/^end$/!d'
Run Code Online (Sandbox Code Playgroud)

或者使用高级语言的更通用的文本处理工具,例如awkperl...正如您已经发现的那样。

话虽如此,一些grep实现可以更进一步。

pcregrep -M '(?s)^begin$.*?^end$'
Run Code Online (Sandbox Code Playgroud)

那就是使用多行模式 ( -M); (?s)切换sPCRE regexp 中的标志,以便.也匹配换行符。

对于当前版本的pcregrep,如果beginend相距超过 20kiB(或指定的缓冲区大小),则不能保证工作。

例如,它将匹配

(seq 12091; echo begin; seq 4315; echo end; seq 10) |
   pcregrep -M '(?s)^begin$.*?^end$'
Run Code Online (Sandbox Code Playgroud)

但不是在:

(seq 12091; echo begin; seq 4316; echo end; seq 10) |
   pcregrep -M '(?s)^begin$.*?^end$'
Run Code Online (Sandbox Code Playgroud)

或者使用grepPCRE 支持构建的GNU并假设文件不包含 NUL 字符:

grep -zoP  '(?ms)^begin$.*?^end$'
Run Code Online (Sandbox Code Playgroud)

然而,这意味着grep在开始搜索之前将整个文件加载到内存中,因此除了小文件外不应使用。它还在输出中附加一个 NUL 字符。

在任何情况下,grep走这里的正道。