我正在尝试删除打印到文件中的错误消息。我有这个:
addr:1122c:1234:
addr:11230:5678:
addr:11223:01Error:abcdef(x, y) = z, value = a
Error:hijklm(v, q) = w, value = b
Error:nopqrst(x, y) = z, value = d
Error:uvwxyz(l, m) = z, value = e
Error:1234(u, t) = z, value = f
Error:567(r, s) = z, value = g
err_total = 9846, err_sub = 0, err_mask = 239
1 Duration: xyz, abc
0 Duration: pqr, def
23:
addr:11238:4567:
addr:1123c:8901:
我需要删除直到出现下一个地址为止的所有错误消息。所需输出为:
addr:1122c:1234:
addr:11230:5678:
addr:11223:0123:
addr:11238:4567:
addr:1123c:8901:
我努力了:
sed -i "/\bError\b/d" file_name
但是这会删除从 Error 开始的行,而不会删除从中间开始 Error 字符串的行。
我对正则表达式还不熟悉,解释一下会很有帮助。
编辑:我正在使用,sed -i '/Error/,/addr/d' filename
但这会删除整行并且不会提供我想要的内容。
答案1
sed
在多行匹配方面并不是很好。
你可以欺骗它做你想做的事,但在我看来这样perl
更容易处理。
尝试这个:
perl -pe 'BEGIN{undef $/;}; s/Error.*?(^[0-9]* Duration: [^\n]*\n)+//smg;'
解释:
BEGIN { do_something; }
:一开始就做一次undef $/
:忽略行尾s///
代替Error.*
匹配以“Error”开头的任何字符串。?
使前一个匹配不贪婪,因为它会在下一个匹配或在这种情况下匹配组时停止......()+
创建一个匹配组,该组至少需要匹配一次(+
)。^[0-9]* Duration: [^\n]*\n
:匹配包含持续时间的整行。
(通过)
答案2
除了删除“ Error:
”行之外,为什么不使用以下命令提取所需的行:
grep -E '^ addr:' file_name | sed -e 's/Error:.*//'
答案3
这将生成您一直在寻找的输出:
$ cat file_name | grep -v \
-e '^Error:' \
-e '^err_total' \
-e '^.*[0-9] Duration:' | \
sed ':a;$!N;s/Error:.*\n\(.*[0-9]\):/\1:/;ta;P;D'
首先删除所有Error
、err_total
和12345 Duration:
内容。然后搜索Error: ...
中断输出的内容,删除换行符 ( \n
),搜索下一个数字 ( .*[0-9]:
) 并将其附加到当前行。