删除匹配模式的行,以及其后面匹配不同模式的任何行

删除匹配模式的行,以及其后面匹配不同模式的任何行

让我先说一下,我不确定以前是否有人问过这个问题,我一直在谷歌上搜索答案,但没有找到答案。

我想使用标准 Linux/Unix 命令(在 FreeBSD 上运行)来排除日志文件中与模式匹配的行。日志文件还包括“最后一条消息重复 x 次”以压缩日志条目。

作为一个例子,我想以此为例:

May 27 2023 11:07 relevant information #1
May 27 2023 11:07 relevant information #2
May 27 2023 11:08 last message repeated 3 times
May 27 2023 11:08 useless information #1
May 27 2023 11:08 last message repeated 5 times
May 27 2023 11:09 last message repeated 8 times
May 27 2023 11:09 relevant information #3
May 27 2023 11:09 useless information #2
May 27 2023 11:10 useless information #3
May 27 2023 11:10 last message repeated 6 times

并得到这个输出:

May 27 2023 11:07 relevant information #1
May 27 2023 11:07 relevant information #2
May 27 2023 11:08 last message repeated 3 times
May 27 2023 11:09 relevant information #3

我已经使用 sed 命令来做到这一点,但我不太了解它是如何工作的来弄清楚它。当涉及到后面有多个“最后一条消息重复”的日志行时,我尤其迷失了。这是我目前正在处理的内容:

sed '/useless information/{d;N;/last message repeated/d;}' ./logfile.txt

上面首先删除包含“无用信息”的匹配行,然后将下一行添加到名称空间中N,然后如果结果行包含“最后一条消息重复”,则应该删除它。但它只是删除带有“无用信息”的行。

答案1

如果您可以测试相关信息而不是无用信息,请在每个 Unix 机器上的任何 shell 中使用任何 awk:

awk '/last message repeated/ && f; {f=/relevant information/} f' file
May 27 2023 11:07 relevant information #1
May 27 2023 11:07 relevant information #2
May 27 2023 11:08 last message repeated 3 times
May 27 2023 11:09 relevant information #3

答案2

pcregrep

$ pcregrep -vM 'useless information(.*\n.*message repeated)*' your-file
May 27 2023 11:07 relevant information #1
May 27 2023 11:07 relevant information #2
May 27 2023 11:08 last message repeated 3 times
May 27 2023 11:09 relevant information #3

-MispcregrepM多行模式根据正则表达式匹配的需要将额外的行拉入模式空间(在限制内)。启用后,将启用mperl/PCRE 标志(它在主题内每行的开头/结尾处进行^匹配$,而不是仅在主题的开头/结尾处进行匹配),并且该s标志(这.也使得匹配换行符)不是启用这解释了为什么.*上面的那些尽管贪婪却不会吞噬整个输入。

对于sed,可以是这样的:

sed -n '
  :start
  /useless information/ {
    :more
    n
    /message repeated/ b more
    b start
  }
  p'

awk

awk '! (useless && /message repeated/ || \
        (useless = /useless information/))'

请注意,至少需要在 busybox 中(...)进行分配。uselessawk

相同于perl

perl -ne 'print unless $useless and /message repeated/ or
            $useless = /useless information/'

(使用and/or代替&&/,||因为它们的优先级低于=删除括号的需要;请参阅perldoc perlop参考资料)。

答案3

使用 Raku(以前称为 Perl_6)

~$ raku -ne '.put unless my $useless and /message \s repeated/ or $useless = /useless \s information/;'  file

#OR

~$ raku -ne '.put unless my $useless and / "message repeated" / or $useless = / "useless information" /;'  file

#OR

~$ raku -ne '.put unless my $useless and m:s/message repeated/ or $useless = m:s/useless information/;'  file 

采用 @Stéphane Chazelas 出色的 Perl 答案并翻译为 Raku。注意 Raku 对于泄露的内容更加明确put。这里,是加载了逐行文本的主题变量的.put缩写。 (另外,还为您添加换行符终止符)。$_.put$_put

第二个区别是默认情况下,正则表达式匹配器中的空格并不重要。因此(从第一个示例开始),message \s repeated将匹配输入,双引号字符串也将匹配"message repeated"

但未加引号message repeated和/或未加引号useless information都将无法与大量错误匹配:

Space is not significant here; please use quotes or :s (:sigspace) modifier (or, to suppress this warning, omit the space, or otherwise change the spacing)

这就是上面第二个和第三个代码示例的起源。

https://docs.raku.org/language/regexes#Sigspace
https://docs.raku.org/routine/put
https://raku.org

相关内容