sed - 如果一行与条件匹配,则打印与模式范围匹配的行

Bra*_*rad 13 sed text-processing

我有一个需要处理的多行日志条目格式。

日志看起来像这样:

--START--
Device=B
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=B
Data=asdfasdf
--END--
--START--
Device=A
Data=asdfasdf
--END--
--START--
Device=B
Data=asdfasdf
--END--
--START--
Device=C
Data=asdfasdf
Lorem=Ipsum
--END--
Run Code Online (Sandbox Code Playgroud)

我想打印之间的一切--START----END--某一特定模式匹配。

例如:

打印所有条目 Device=A

--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--
Run Code Online (Sandbox Code Playgroud)

到目前为止我能做的就是写:

sed -e -n '/--START--/,/--END--/p' < input
Run Code Online (Sandbox Code Playgroud)

这有效地打印了输入,但我认为我需要添加{}到过滤器,N然后打印该条件是否匹配。

我也觉得我完全迷失了。

如果单行符合条件,如何打印多行的任何想法?

Joh*_*024 24

$ sed -n '/--START--/{:a;N;/--END--/!ba; /Device=A/p}' file
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--
Run Code Online (Sandbox Code Playgroud)

(以上是在 GNU sed 上测试过的。它必须经过调整才能在 BSD/OSX 上运行。)

这个怎么运作:

  • /--START--/{...}

    每次我们到达包含 的行时--START--,运行大括号内的命令{...}

  • :a

    定义标签a

  • N

    阅读下一行并将其添加到模式空间。

  • /--END--/!ba

    除非模式空间现在包含--END--,否则跳回标签a

  • /Device=A/p

    如果我们到达这里,这意味着模式空间以 开始--START--并以 结束--END--。此外,如果模式空间包含Device=A,则打印 ( p) 它。


Cos*_*tas 6

sed使用保持空间的其他变体

sed 'H              #add line to hold space
     /--START--/h   #put START into hold space (substitute holded in)
     /--END--/!d    #clean pattern space (start next line) if not END
     x              #put hold space into pattern space
     /Device=A/!d   #clean pattern space if it have not "Device=A"
    ' file
Run Code Online (Sandbox Code Playgroud)