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

Bash 如何在一个图案和以另一个图案开始的线条之间打印线条?,bash,awk,sed,grep,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 2

我需要你的帮助,用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
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
详细说明:

总体思路是只过滤包含“name:Jhon”(不包含whater:Jhon)及其相应日志文本(可以包含任何内容,并且没有时间戳!)的行

我在每行末尾编号,以使3组可能的情况更加明显(日志文本以“which: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
但是这是错误的,因为我认为“任何”都是固定的模式,而且,在这种情况下,包含“任何东西”的线都不被过滤。事实上,“whatever”和“anything”(以及随机文本和时间)可以是任何文学。因此,停止匹配的唯一方法是在以日期格式开头的行上停止匹配(但我不能使用2019,因为它被用于每个非LOG_文本行)


还尝试了一些JS正则表达式,但它太复杂了

最终输出应如下所示:

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
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

我想试试这样的东西:

 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/将检查变量
    a
    是否匹配
    pattern
  • 在代码中,您使用了
    /Jhon/{flag=1}
    。此表达式只是
    $0~/Jhon/{flag=1}
    的快捷方式。如果行($0)与模式匹配,则将执行块
    {flag=1}
  • $1~/[0-9]{4}-[0-9]{2}-[0-9]{2}/
    表示如果行的第一列与日期格式匹配,则将执行块


但当然,如果日志文本以日期开头,它将失败

如果日志文本始终在两行上,您可以尝试以下操作:

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

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

日志文本是任意行数的任意随机文本。我测试了你的awk,看起来不错。在我的例子中,LOG_文本不会以日期开头(因为它实际上是一个JSON)。如果我发现任何情况都不起作用,我会回来的。你介意解释一下小部分背后的逻辑吗?我不确定我是否理解您如何使用“~”。多谢各位!