我的日志文件包含多行,用于单个日志输出,如下所示:
DEBUG : <line1>
<line2>
TRACE : <line11>
<line12>
<line13>
DEBUG : <line21>
<line22>
<line23>
TRACE : <line31>
<line32>
ERROR : <line41>
<line42>
TRACE : <line51>
<line52>
DEBUG : <line61>
<line62>
我必须从TRACE输出中清除它。
我用
sed -e "/^TRACE/,/^DEBUG\|^ERROR/d" <log.txt
...并获得
DEBUG : <line1>
<line2>
<line22>
<line23>
<line42>
<line62>
Sed包含删除范围,并且在TRACE块之后不会打印DEBUG和ERROR行。 我用sed尝试了其他方法,但没有找到如何仅删除TRACE块。
Sed非常好,但也许我应该使用另一个Unix实用程序......请建议。
答案 0 :(得分:2)
这是一种在sed中做你想要的方法,虽然这是我通常使用perl的情况。这使用sed的“保留空间”来收集日志文件的每个部分,并在看到下一部分的开头时打印(或不打印)整个部分。
sed -n -e '/^\(TRACE\|DEBUG\|ERROR\)/ ! { H ; $!b } ; x ; /^\(DEBUG\|ERROR\)/ p'
但是,回答问题的主题,我认为不可能从范围中排除最后一行。
答案 1 :(得分:0)
awk '/^TRACE/ {
while ( $0 !~ /^DEBUG/ || $0 !~ /^ERROR/ ) {
getline ;
if ( $0 ~ /^DEBUG/ || $0 ~ /^ERROR/ ) {
print $0 ;
next
}
}
}
{ print $0 }' FILENAME
AWK救援;-)(注意:它可以粘贴到一行。)
答案 2 :(得分:0)
这提供了将输入分成不同位置的合理技术。使用一个案例会很好,但如果你坚持将字符串锚定在行的开头,我不相信这是可能的。
#!/bin/sh exec 3>&1 exec 4> /dev/null exec 5>&1 while read -r line; do echo $line | grep ^DEBUG >&3 && exec >&3 && continue echo $line | grep ^TRACE >&4 && exec >&4 && continue echo $line | grep ^ERROR >&5 && exec >&5 && continue echo $line done
答案 3 :(得分:0)
您可以复制标记,只删除第一个标记:
sed -E "s/^((DEBUG)|(ERROR)) : /\1 : \n\1 /" | \
sed "/^TRACE/,/^DEBUG\|^ERROR/d" | sed "s/^</\t</"
DEBUG :
DEBUG <line1>
<line2>
DEBUG <line21>
<line22>
<line23>
ERROR <line41>
<line42>
DEBUG <line61>
<line62>
最后一个sed命令只是为了更好的可读性,第一行留作练习。 :)