Difference between revision 17 and current revision
Summary: Rollback to 2011-06-28 09:12 UTC
No diff available.The following snippets print matching lines with surrounding context lines, like GNU grep's grep -A N (N lines after), grep -B N (num lines before), and grep -C N (num lines before and after), and all in about double the time :)
Printing the match followed by N lines is the easiest and fastest, since we don't have to save any lines. The following expects two variables to be set: Pattern (a regex to match), and After (the number of lines to print after each match).
$0 ~ Pattern { # if we found the pattern ... if (seen++ && NR>afterlineno+1) # if we already found another block # and are outside a context block print "--" # ... print a divider afterlineno = NR + After } NR <= afterlineno
Or as a oneliner (3 lines of context, with "Regex" as pattern):
awk -v N=3 '/Regex/{if (seen++ && NR>a+1)print "--"; a = NR+N} NR<=a'
Printing N lines before a match is trickier and slower, because we need to save lines, as we don't know yet whether they should be printed. It's possible to minimize the number of lines saved by deleting extra saved lines as you read the file, but this slows down the process significantly. Here's a way of doing it (this time, the script expects the variables Pattern and Before (number of lines before) to be set:
$0 ~ Pattern { if (lineno && (last+Before+1)<NR) # if we already printed a block # and not within a block print "--" # ... print a divider lineno = NR-Before # set the array index to start printing if (lineno<last) # check if contexts overlap lineno = last+1 for ( ; lineno < NR; lineno++) if (lineno in lines) print lines[lineno] print last = NR next } { lines[NR] = $0 # ... or save the line }
The variable last keeps track of the last line printed, so lines are not repeated when contexts overlap.
The following combines the two previous scripts. This script expects the variables Pattern and Context (number of lines to print before and after a match):
$0 ~ Pattern { afterlines = NR + Context if (seen++ && (last+Context+1)<NR) print "--" lineno = NR-Context if (lineno<last) lineno = last+1 for ( ; lineno < NR; lineno++) if (lineno in lines) print lines[lineno] } NR <= afterlines { print last = NR next } { lines[NR]=$0 }