Grep/awk/sed 有状态线路匹配
Grep/awk/sed stateful line matching
我有一个日志文件,其中包含的条目本身可以分为多行,我想找到这些条目的所有实例。
例如:
AAA normal line
BBB normal line
XXX important line
important line continuation 1
important line continuation 2
BBB normal line
normal line continuation 1
AAA normal line
XXX important line
important line continuation 1
important line continuation 2
important line continuation 3
AAA normal line
所有条目均以代码开头(AAA、BBB、XXX 等)。以代码 XXX 开头的行及其关联的续行是我感兴趣的行。续行以 space 开头,并且可以有任意数量的续行。续行之后的行可以任何代码开头。
我认为这是一种 'stateful' 匹配(虽然它可能无法通过这种方式解决)...即:我想要匹配模式 XXX 的行,然后所有紧接着以 [= 开头的行=28=](直到他们不这样做)。
我如何在拖尾日志文件的同时为此使用 grep、sed 或 awk?
更新: 示例期望结果:
XXX important line
important line continuation 1
important line continuation 2
XXX important line
important line continuation 1
important line continuation 2
important line continuation 3
这个 awk
应该有效:
awk '/^[^ \t]/{p = ( == "XXX")} p' file
XXX important line
important line continuation 1
important line continuation 2
XXX important line
important line continuation 1
important line continuation 2
important line continuation 3
命令说明:
/^[^ \t]/
:条件,如果一行不是以space或制表符 开头
{
: 启动动作块
p = ( == "XXX")
:如果第一列是 XXX
,则将 p
设置为 1
,否则将其设置为 0
。
}
: 结束块
p
:如果p==1
则打印行
当我们找到 == XXX
时,p
将被设置为 1
,并且我们将继续打印行,直到 p
再次变为 0
。
这可能适合您 (GNU sed):
sed '/^XXX/{:a;n;/^ /ba};d' file
如果一行以 XXX
开头,打印它然后获取下一行。
如果该行以 space 开头,打印它并获取下一行并重复。
将删除任何其他行。
N.B。 n
通常打印模式 space 中的当前行,然后用下一行替换它。这是 sed 中的正常循环,例如sed '' file
将只打印文件。如果使用 -n
选项,则不执行隐式打印,因此:
sed -n '/^XXX/{:a;p;n;/^ /ba}' file
实现相同的结果。
如果行的开头可能是制表符或任何白色 space,请使用:
sed '/^XXX/{:a;n;/^\s/ba};d' file
我有一个日志文件,其中包含的条目本身可以分为多行,我想找到这些条目的所有实例。
例如:
AAA normal line
BBB normal line
XXX important line
important line continuation 1
important line continuation 2
BBB normal line
normal line continuation 1
AAA normal line
XXX important line
important line continuation 1
important line continuation 2
important line continuation 3
AAA normal line
所有条目均以代码开头(AAA、BBB、XXX 等)。以代码 XXX 开头的行及其关联的续行是我感兴趣的行。续行以 space 开头,并且可以有任意数量的续行。续行之后的行可以任何代码开头。
我认为这是一种 'stateful' 匹配(虽然它可能无法通过这种方式解决)...即:我想要匹配模式 XXX 的行,然后所有紧接着以 [= 开头的行=28=](直到他们不这样做)。
我如何在拖尾日志文件的同时为此使用 grep、sed 或 awk?
更新: 示例期望结果:
XXX important line
important line continuation 1
important line continuation 2
XXX important line
important line continuation 1
important line continuation 2
important line continuation 3
这个 awk
应该有效:
awk '/^[^ \t]/{p = ( == "XXX")} p' file
XXX important line
important line continuation 1
important line continuation 2
XXX important line
important line continuation 1
important line continuation 2
important line continuation 3
命令说明:
/^[^ \t]/
:条件,如果一行不是以space或制表符 开头
{
: 启动动作块p = ( == "XXX")
:如果第一列是XXX
,则将p
设置为1
,否则将其设置为0
。}
: 结束块p
:如果p==1
则打印行
== XXX
时,p
将被设置为 1
,并且我们将继续打印行,直到 p
再次变为 0
。
这可能适合您 (GNU sed):
sed '/^XXX/{:a;n;/^ /ba};d' file
如果一行以 XXX
开头,打印它然后获取下一行。
如果该行以 space 开头,打印它并获取下一行并重复。
将删除任何其他行。
N.B。 n
通常打印模式 space 中的当前行,然后用下一行替换它。这是 sed 中的正常循环,例如sed '' file
将只打印文件。如果使用 -n
选项,则不执行隐式打印,因此:
sed -n '/^XXX/{:a;p;n;/^ /ba}' file
实现相同的结果。
如果行的开头可能是制表符或任何白色 space,请使用:
sed '/^XXX/{:a;n;/^\s/ba};d' file