准确地说
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)
怎么办grep
?grep
在某些 *nix 上是否有任何实现可以完成?
grep
即g/re/p
是一个基本工具p RINT匹配的所有行ř egular ë上的表达。
更多在这里像你想小号tream ED itor:
sed '/^begin$/,/^end$/!d'
Run Code Online (Sandbox Code Playgroud)
或者使用高级语言的更通用的文本处理工具,例如awk
,perl
...正如您已经发现的那样。
话虽如此,一些grep
实现可以更进一步。
pcregrep -M '(?s)^begin$.*?^end$'
Run Code Online (Sandbox Code Playgroud)
那就是使用多行模式 ( -M
); (?s)
切换s
PCRE regexp 中的标志,以便.
也匹配换行符。
对于当前版本的pcregrep
,如果begin
和end
相距超过 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)
或者使用grep
PCRE 支持构建的GNU并假设文件不包含 NUL 字符:
grep -zoP '(?ms)^begin$.*?^end$'
Run Code Online (Sandbox Code Playgroud)
然而,这意味着grep
在开始搜索之前将整个文件加载到内存中,因此除了小文件外不应使用。它还在输出中附加一个 NUL 字符。
在任何情况下,grep
是不走这里的正道。