如何在一个图案和以另一个图案开始的线条之间打印线条?

时间:2019-05-23 09:07:45

标签: bash awk sed grep

在使用AWK(最好)解析日志文件时,我需要您的帮助,以便仅提取必要的信息。我对其进行了简化,使其更加明显,看起来像这样:

2019-05-22 HH:MM:SS name:Jhon 1 + random_text
LOG_TEXT 1
LOG_TEXT 1
2019-05-22 HH:MM:SS whatever:Jhon 1 + random_text
2019-05-22 HH:MM:SS name:Jhon 2 + random_text
LOG_TEXT 2
LOG_TEXT 2
2019-05-22 HH:MM:SS ANYTHING 2 + random_text
2019-05-22 HH:MM:SS name:Jhon 3 + random_text
LOG_TEXT 3
LOG_TEXT 3
2019-05-22 HH:MM:SS name:Jhon 3 + random_text

详细说明:

总体思路是仅过滤包含“ name:Jhon”(不包含任何内容:Jhon)及其相应的LOG TEXT(可以包含任何内容,并且不加时间戳!)的行。

我在每一行的末尾都加上了编号,以使3组可能的情况更加明显(LOG TEXT以“ whatever:JHON”结尾(未打印1行);带有通用日期戳记的行“ ANYTHING”( 2行未打印);或带有“ name:JHON”(3行已打印))


该功能是Vmware Vrealize Orchestrator中工作流的一部分(因此实际语言是JS,但我可以使用ssh和awk),但我不会对此进行深入研究。

我尝试了各种awk和regex模式,但无法弄清楚。 我能得到的最接近的东西与此类似:

awk '/Jhon/{flag=1}/whatever/{flag=0}flag' file.txt

但是这是错误的,因为我认为“任何”都是固定模式,并且在这种情况下,包含“任何”的行也不会被过滤。实际上,“无论是什么”和“任何东西”(以及random_text和时间HH:MM:SS)在文学上可以是任何东西。因此,停止匹配的唯一方法是在以日期格式开头的行上停止它(但是我不能使用2019,因为在每个非LOG_TEXT行上都使用了它)。


也尝试过使用一些JS正则表达式,但这太复杂了。

最终输出应如下所示:

2019-05-22 HH:MM:SS name:Jhon 1 + random_text
LOG_TEXT 1
LOG_TEXT 1
2019-05-22 HH:MM:SS name:Jhon 2 + random_text
LOG_TEXT 2
LOG_TEXT 2
2019-05-22 HH:MM:SS name:Jhon 3 + random_text
LOG_TEXT 3
LOG_TEXT 3
2019-05-22 HH:MM:SS name:Jhon 3 + random_text

1 个答案:

答案 0 :(得分:1)

我会尝试这样的事情:

if-else

说明:

  • a〜/ pattern /将检查变量 awk '$1 ~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/{if($0~/name:Jhon/){flag=1}else{flag=0}}flag' file.txt 是否与a匹配
  • 在您的代码中,您使用了pattern。此表达式只是/Jhon/{flag=1}的快捷方式。如果行($ 0)匹配模式$0 ~ /Jhon/{flag=1},则执行块{flag=1}
  • /John/表示如果该行的第一列与日期格式$1 ~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/(<4位>-<2位>-<2位>)匹配,则将执行该块

    YYYY-mm-dd

但是,当然,如果LOG_TEXT以某个日期开始,它将失败。

如果LOG_TEXT总是两行,则可以尝试以下方法:

awk '
    # If first column matches a date format
    $1 ~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/{
        # If the line contains name:Jhon
        if($0~/name:Jhon/)
        {
            flag=1
        }
        else
        {
            flag=0
        }
    }
    # Prints if flag != 0
    flag
' file.txt

返回

awk '{counter-=1}/name:Jhon/{counter=3}counter>0' file.txt