[Home]
HomePage RecentChanges Frequently Asked Questions

ContextGrep

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 :)

Lines After

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'

Lines Before

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.

Lines Before and After

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ドル
}

Edit this page View other revisions Administration
Last edited 2011年07月01日 08:32 UTC by pgas (diff)

Powered by sdf Creative Commons License <pierre.gaston+awk@gmail.com>

Awk Wiki by #awk is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

AltStyle によって変換されたページ (->オリジナル) /