Reputation: 9
I want to use awk to print 5 lines before and 5 lines after the match regex (Start in ERROR and finish with on of INFO |WARN |DEBUG|TRACE). Also, I need to print the line number as well. I just success to print the line number
cat foo | awk '/\[ERROR\]/,/\[(INFO |WARN |DEBUG|TRACE)/{print NR":"$0}'
I don't care to find a solution with grep command
For example, the file contains:
DEBUG
DEBUG
DEBUG
TRACE
TRACE
INFO
INFO
ERROR
INFO
INFO
INFO
DEBUG
DEBUG
DEBUG
DEBUG
The output should be:
3: DEBUG
4: TRACE
5: TRACE
6: INFO
7: INFO
**8: ERROR
9: INFO**
10: INFO
11: INFO
12: DEBUG
13: DEBUG
14: DEBUG
The stars mark the match regex(Begin in ERROR, end in INFO)
Upvotes: 0
Views: 1979
Reputation: 58371
This might work for you (GNU sed & nl):
nl -s': ' -w1 file |
sed -En ':a;N;s/\n/&/5;Ta
/\n([0-9]+: ERROR[^\n]*)$/{
s//\n**\1/;:b;p;n;/^[0-9]+: INFO/!bb;s/$/**/;:c;tc;N;s/\n/&/5;Tc;p;d};D'
Prepend line numbers using a :
and space as a separator using the nl
command and pipe the results into sed
.
Fetch 5 lines into the pattern space and then check the sixth for the starting pattern.
If the sixth line does not contain the starting pattern, remove the first line, append another to the pattern space and repeat.
If the sixth line does contain the starting pattern, insert **
before the line number of that line, print/clear the pattern space, continue printing all lines until the ending pattern is matched.
Once the ending pattern is matched, prepend **
to end of that line, fetch and append 5 further lines and print the result.
The pattern space is cleared and the normal sed cycle is then resumed and the process repeated.
Upvotes: 0
Reputation: 203189
$ cat tst.awk
{ buf[NR%6] = $0 }
/ERROR/ { tgt=NR; f=1 }
tgt == NR {
for (i=1; i<=6; i++) {
print (NR+i-6) ":", buf[(NR+i)%6]
}
}
f && /INFO|WARN|DEBUG|TRACE/ { tgt=NR+5; f=0 }
.
$ awk -f tst.awk file
3: DEBUG
4: TRACE
5: TRACE
6: INFO
7: INFO
8: ERROR
9: INFO
10: INFO
11: INFO
12: DEBUG
13: DEBUG
14: DEBUG
Upvotes: 3
Reputation: 37394
I submit this awk for peer reviewing, turned my brain to a bowl of spagetti (can't even spell spaghetti correctly):
$ awk '{
$0=NR " " $0 # prepend NR to record
}
!f {
b[6]=$0 # buffer to hold 5 previous lines
for(i=1;i<=5;i++) {
if(/ERROR/) # print previous buffer at ERROR
print b[i]
b[i]=b[i+1]
}
}
/ERROR/,/(INFO|WARN|DEBUG|TRACE)/ { # between markers arm the output flag
f=5
}
f&&f--' file # keeps negative valued flags out
Upvotes: 0