我有一个需要处理的多行日志条目格式。
日志看起来像这样:
--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--
我想打印--START--
和之间的所有内容(--END--
如果特定模式匹配)。
例如:
打印所有条目Device=A
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--
到目前为止我所能做的就是写:
sed -e -n '/--START--/,/--END--/p' < input
它有效地打印输入,但我认为我需要添加{}
到过滤器N
,然后在条件匹配时打印。
我也觉得我完全迷失了。
如果单行匹配条件,您知道如何打印多行吗?
答案1
$ 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--
(上面是在 GNU sed 上测试的。它必须经过调整才能在 BSD/OSX 上运行。)
怎么运行的:
/--START--/{...}
每次到达包含 的行时
--START--
,就运行大括号内的命令{...}
。:a
定义一个标签
a
。N
读取下一行并将其添加到模式空间。
/--END--/!ba
除非模式空间现在包含
--END--
,否则跳回 labela
。/Device=A/p
如果我们到达这里,这意味着模式空间以 开始
--START--
并以 结束--END--
。另外,如果模式空间包含Device=A
,则打印 (p
) 它。
答案2
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
答案3
和sed
:
$ -e:1 -e'$!N;/--END--/{
/Device=A/!d
b
}' -eb1 <file
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--
--START--
这会将之间和之间的所有行读取--END--
到模式空间中。如果匹配--END--
,我们检查模式空间是否不包含Device=A
,将其删除,否则sed
打印模式空间然后开始下一个循环。
和awk
:
awk '
/--START--/ {
getline d
if (d ~ /Device=A/) {
p = 1
printf "%s\n%s\n", $0, d
next
}
}
p
/--END--/ { p = 0 }
' <file
答案4
这里已经有其他几个很好的答案,它们演示了如何测试之间的字符串--START--
和--END--
块,但是,考虑到您的示例输入,您可能不需要真正担心--START--
根本不。
sed -n '$!N;/^Device=A\n/,/\n--END--/P;D'
...将打印所有内容Device=A
\n
直到下一个发生之前发生的最后一个ewline--END--
在每个块中。不用担心--START--
因为它似乎没有必要检查它。
所以对于像这样的块:
--START--
Device=A
...stuff...
--END--
...输出将是...
Device=A
...stuff...
...但是对于像这样的块...
--START--
Device=B
Device=A
...stuff...
--END--
...它会输出相同的结果。
它的工作原理是将 ext 输入行附加到不是最后N
一行的每一行,因此模式空间如下所示:!
$
^line1\nline2$
对于序列之间出现的每个模式空间^Device=A\n
和\n--END--
当前模式中的两行中的第一行被P
打印,然后D
删除,然后用剩余的内容开始下一个循环。所以下一个模式空间看起来像......
^line2\nline3$