我有一个日志文件,它与stderr结合,我试图清理。我可以隔离并发现stderr“污染”,但我正在努力解决一个小细节:删除换行符
这是我尝试恢复的单独标准输出:
some message 1234556
more info foo bar
这是我试图摆脱stderr消息的组合stdout / stderr文件:
some message 1234/some/path ERROR
more info only 1 line though
556
more info foo bar
所以这是我试图摆脱的文字:
/some/path ERROR
more info only 1 line though
包括换行符,以便恢复单独的stdout。
我打电话:
# get rid of the line AFTER the stderr start
sed -i".bak" -e '/ERROR/{n;d}' *.log
# get rid of the start of stderr
sed -i".bak" -r 's/\/some\/path.*ERROR//' *.log
不幸的是,输出现在是:
some message 1234
556
more info foo bar
注意,stderr消息的插入点可以是任意的(在行的中间或开头的任何地方)。我唯一可以假设的是stderr是一个双线程,它以/some/path
开头并包含一个错误标识符(ERROR
或其他)。此外,可能有多个后续的stderr消息,例如:
some message 1234/some/path ERROR
more info only 1 line though
/some/path ANOTHER_ERR
more info only 1 line though
556
more info foo bar
我认为这不会造成太大的问题(只有2种,所以我可以运行多个不同的比赛(ERROR
和ANOTHER_ERR
))。我也不关心使用哪种工具sed
或awk
...
对于一些基本的sed来说似乎很完美。只需使用N
将下一行吞入模式空间即可。
sed '/ERROR/{N;s/\/.*//;N;s/\n//g}' input.log
N
将下一行添加到模式空间N
将下一行添加到模式空间这与OP与n
的尝试并不遥远。
要将其扩展到后面的示例,您可以回到开头查看N
命令是否将更多错误字符串带入模式空间:
sed -E ':a /(ERROR|ANOTHER_ERR)/{N;s/\/.*//;N;s/\n//g;b a}'
-E
允许两个模式的parens:a
b a
就会回到:a
。我宁愿避免使用sed -z
。它会将整个文件读入模式空间,因此如果此日志文件很长,或者您正在将活动流传输到sed,它可能不是最佳选择。
您可以使用perl
强大的段落模式选项。 -00
命令行选项打开段落slurp模式,意味着Perl逐段读取文本,而不是逐行读取(段落是两个或多个换行符之间的文本。)
perl -00 -pe 's/\/.*(ERROR|ANOTHER_ERR)\n.*\n//g' file
要在适当位置添加修改,请添加-i
标志,类似于sed
perl -00 -pi -e 's/\/.*(ERROR|ANOTHER_ERR)\n.*\n//g' file
使用GNU sed for -E和-z:
$ sed -Ez 's:/some/path ERROR\n[^\n]+\n::g' file
some message 1234556
more info foo bar
如果你有多个错误需要处理,那么只需在正则表达式中列出或分隔:
$ cat file
some message 1234/some/path ERROR
more info only 1 line though
/some/path ANOTHER_ERR
more info only 1 line though
556
more info foo bar
$ sed -Ez 's:/some/path (ERROR|ANOTHER_ERR)\n[^\n]+\n::g' file
some message 1234556
more info foo bar
或者,使用GNU awk进行多字符RS:
$ awk -v RS='/some/path ERROR\n[^\n]+\n' -v ORS= '1' file
some message 1234556
more info foo bar
或者如果您愿意:
$ awk -v RS='^$' -v ORS= '{gsub("/some/path ERROR\n[^\n]+\n","")}1' file
some message 1234556
more info foo bar
没有-z
选项的另一种sed解决方案:
$ sed -E -n '/ERROR/{s@/.*@@;h;n;n;H;n;H;x;s/\n//;p}' input.log
some message 1234556
more info foo bar