3

I am trying to remove the error messages printed into my file. I have this:

 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:

I need to remove all the error messages upto the next addr appears. Required output is:

 addr:1122c:1234:
 addr:11230:5678:
 addr:11223:0123:
 addr:11238:4567:
 addr:1123c:8901:

I have tried:

sed -i "/\bError\b/d" file_name

But this removes the lines starting from Error and did not remove the line where Error string started from the middle.

I am new to regular expressions, an explaination would be really helpful.

Edit: I am using sed -i '/Error/,/addr/d' filename but this removes the whole line and does not give what I am looking for.

3 Answers 3

4

sed is not really good in Multiline Matching.
You can trick it to do what you want, but then imo perl is easier to handle.

Try this:

perl -pe 'BEGIN{undef $/;}; s/Error.*?(^[0-9]* Duration: [^\n]*\n)+//smg;'

Explanation:

  • BEGIN { do_something; }: Do something once at the beginning
  • undef $/: Ignore line endings
  • s/// Substitute
  • Error.* Match any string beginning with "Error".
  • ? Make the previous match ungreedy, for that it stops at the following match or in this case matching group...
  • ()+ Make a matching group, that needs to be matched at least once (+).
  • ^[0-9]* Duration: [^\n]*\n: Match the whole line with Duration including.

(via)

2
  • Thank you for the answer, works like a charm for the example i gave. However, I had a different example I was working on. I have updated the question, can u please take a look and suggest changes? Aug 6, 2018 at 10:28
  • 1
    Updated the answer.
    – pLumo
    Aug 6, 2018 at 11:31
2

Rather than deleting the "Error:" lines, why not extract just the lines you want with:

grep -E '^ addr:' file_name | sed -e 's/Error:.*//'
3
  • I have other lines in the file that does not begin with 'addr' but are needed. Hence I asked for way to remove the unwanted lines. Aug 6, 2018 at 13:38
  • 2
    I refuse to track a problem that's revealed a tiny bit at a time. You keep changing requirements, and that's unacceptable.
    – waltinator
    Aug 6, 2018 at 13:57
  • Sorry for the miscommunication, my intention was just to remove the unwanted lines and I guess I dint convey it in the best way. Nevertheless, thank you for your answer, upvoted. Aug 7, 2018 at 5:41
1

This will generate the output you have been looking for:

$ 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'

Frist remove all the Error, err_total, and 12345 Duration: stuff. Then search for the Error: ... interrupting your output, remove the newline(\n), search for the next occurence of a number (.*[0-9]:) an append it to the current line.

1
  • Thank you for the answer, works like a charm for the example i gave. However, I had a different example I was working on. I have updated the question, can u please take a look and suggest changes? Aug 6, 2018 at 10:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .