让我先说一下,我不确定以前是否有人问过这个问题,我一直在谷歌上搜索答案,但没有找到答案。
我想使用标准 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
-M
ispcregrep
的M
多行模式根据正则表达式匹配的需要将额外的行拉入模式空间(在限制内)。启用后,将启用m
perl/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 中(...)
进行分配。useless
awk
相同于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