bob*_*bel 10 text-processing regular-expression
我想在一个文件中以一种非贪婪的方式抓取一个具有开始和结束标记的模式的多行。
例如,我有以下输入:
文件.txt
START
test1
test2
foo
END
some
more text
START
test3
bar
test4
test5
END
even more
START
baz
test6
END
Run Code Online (Sandbox Code Playgroud)
现在我想查找bar并打印出START和END之间的所有内容,以便我得到:
START
test3
bar
test4
test5
END
Run Code Online (Sandbox Code Playgroud)
到目前为止,我所拥有的是以下 grep 命令:
grep -Pzo '(?s)START.*?bar.*?END' file.txt
Run Code Online (Sandbox Code Playgroud)
问题是,这个表达式是贪婪的并打印出:
START # starts at first "START"-tag, not the next one
test1 #
test2 #
foo #
END #
some #
more text #
START
test3
bar
test4
test5
END
Run Code Online (Sandbox Code Playgroud)
这不是用 grep 标志--before-context / --after-context 完成的,因为前后的行数可能不同。
文本处理使用的工具无关紧要。它应该适用于一般的 RedHat 系统。此外,工具抓取线条的速度越快,效果就越好。因为我有每个大约 150MB 的大日志文件。
有人能告诉我,如何以最好的方式实现我的目标吗?
好的,我明白了。我只需要考虑如何从don_crissti
s 链接构建我的命令。这是解决方案:
ed -s file.txt <<< $'g/bar/?START?,/END/p\nq\n'
Run Code Online (Sandbox Code Playgroud)
非常感谢您提供的所有快速帮助!
是的,最后它是重复的......
我会使用 awk,您可以在其中指定记录分隔符。如果记录分隔符是“END”(在其自己的行上),则查找包含“bar”的记录:
awk 'BEGIN {RS = ORS = "\nEND\n"} /bar/' file.txt
Run Code Online (Sandbox Code Playgroud)
处理出现在 START 和 END 标记之间的文本。此更改感觉很hacky,但它适用于这种情况:使用 END 作为记录分隔符,删除 START 关键字之前的任何文本
awk '
BEGIN {RS = ORS = "\nEND\n"}
{sub(/^.*\nSTART\n/, "START\n")}
/bar/
' file.txt
Run Code Online (Sandbox Code Playgroud)
如果“START”在 END 之前出现多次,则可能不会给出所需的结果
foo
START
hello
START
bar
world
END
baz
Run Code Online (Sandbox Code Playgroud)
将输出为
START
bar
world
END
Run Code Online (Sandbox Code Playgroud)