从匹配字符串的行中间删除所有行,直到找到第二个匹配的字符串

从匹配字符串的行中间删除所有行,直到找到第二个匹配的字符串

我正在尝试删除打印到文件中的错误消息。我有这个:

 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'

首先删除所有Errorerr_total12345 Duration:内容。然后搜索Error: ...中断输出的内容,删除换行符 ( \n),搜索下一个数字 ( .*[0-9]:) 并将其附加到当前行。

相关内容