如何排除SED范围内的最后一行

时间:2011-04-08 16:05:06

标签: sed

我的日志文件包含多行,用于单个日志输出,如下所示:

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实用程序......请建议。

4 个答案:

答案 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命令只是为了更好的可读性,第一行留作练习。 :)