(Unix)根据模式显示一行Lines

时间:2015-12-04 10:10:02

标签: bash unix sed grep

我想在日志文件中列出所有错误消息,如下所示,并提供错误的完整描述。

00:02:00:00 Here I found an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a System Error (DESCRIPTION_ENDS)
00:02:00:00 
00:02:00:00 Some General Message
00:02:00:00 Some General Message
00:02:00:00 
00:02:00:00 Again got an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a Critical Error (DESCRIPTION_ENDS)
00:02:00:00 
00:02:00:00 Some General Message
00:02:00:00 Some General Message

我正在寻找一个逻辑,可能使用grep或sed,它只显示带描述的ERROR块。

输出:

00:02:00:00 Here I found an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a System Error (DESCRIPTION_ENDS)

00:02:00:00 Again got an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a Critical Error (DESCRIPTION_ENDS)

为了实现这一点,我能想到的唯一逻辑是读取整个文件并打印出有" ERROR"直到包含" DESCRIPTION_ENDS"。

的行

可以使用grep或sed实现吗?如果没有,unix中的任何其他命令,可以通过它来实现吗?

4 个答案:

答案 0 :(得分:1)

awk是一个选项:

awk '/ERROR/ {on=1} on==1 {print} /DESCRIPTION_ENDS/ {on=0; print ""}' data

说明:有3条规则,awk按顺序应用它们。

  • 如果该行与/ERROR/ {on=1}模式匹配,则第一个(awk)设置on变量ERROR
  • 如果设置了on==1 {print}变量awk,则第二行(on)会打印当前行。
  • 第三个(/DESCRIPTION_ENDS/ {on=0; print ""})清除awk变量on,如果该行符合DESCRIPTION_ENDS模式,则插入一个空行。

答案 1 :(得分:1)

awk解决方案:

awk '/ERROR/{f=1};f;/(System|Critical) Error/{print "";f=0}' infile

检查http://klashxx.github.io/awk-between-two-patterns/以获取详细说明。

<强>结果

00:02:00:00 Here I found an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a System Error (DESCRIPTION_ENDS)

00:02:00:00 Again got an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a Critical Error (DESCRIPTION_ENDS)

还有一个sed替代品(根据我的口味不太灵活):

sed -nr '/\s+ERROR/,/\s+Error\s+\(/p' infile

将输出:

00:02:00:00 Here I found an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a System Error (DESCRIPTION_ENDS)
00:02:00:00 Again got an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a Critical Error (DESCRIPTION_ENDS)

答案 2 :(得分:1)

使用触发器范围运算符的Perl单线解决方案

这实际上只是一个单行,但为了便于阅读,它已经扩展了一点。它依赖于PERLOP(1)中定义的触发器范围运算符,以线路方式匹配块的开始和结束。例如:

$ perl -ne 'print if /ERROR/.../DESCRIPTION_ENDS/;
            print "\n" if /DESCRIPTION_ENDS/;
           ' /tmp/corpus
00:02:00:00 Here I found an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a System Error (DESCRIPTION_ENDS)

00:02:00:00 Again got an ERROR
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 Description
00:02:00:00 This is a Critical Error (DESCRIPTION_ENDS)

额外的print语句实际上只是在你的块之间创建段落以提高可读性,并且在每种语言的段落模式打开时使其更适合Perl,Awk或Ruby使用。如果需要,这将简化进一步处理。

答案 3 :(得分:0)

我知道这不是您想要的(但这更简单),但您可以尝试搜索错误并使用-A选项为grep提供一些上下文。

grep -A 5 "ERROR" myFile

我意识到我已经将上下文硬编码到固定的5行,这可能无法解决您的问题,但如果您所做的只是手动搜索日志文件,那么它可能已经足够了。

如果你的描述有一些格式,那么你可以将结果输入第二个grep,所以它只包含你想要的行。