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.

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)

  • 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? – lost_wanderer Aug 6 '18 at 10:28
  • 1
    Updated the answer. – pLumo Aug 6 '18 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:.*//'
  • 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. – lost_wanderer Aug 6 '18 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 '18 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. – lost_wanderer Aug 7 '18 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.

  • 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? – lost_wanderer Aug 6 '18 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.