How can I set the grep after context to be "until the next blank line"?

With grep I know how to set the context to a fixed number of lines. Is it possible to show a context based on an arbitrary string condition, like set after-context to "until the next blank line"?

Or possibly some other combination of tools?

Basically I have a log file of contiguous lines, with blank lines separating the "events" I want to search for a string in the log file, but show the whole event....


Solution 1:

It sounds like you need sed:

sed -n '/pattern/,/^$/p' file

Don't print by default (-n). For lines that match /pattern/ up to an empty line /^$/, print.

Solution 2:

A simple solution is:

awk '/pattern/' RS= input-file

Setting RS to the empty string makes awk treat blank lines as the record separator, and the simple rule /pattern/ causes awk to print any record that matches the pattern, which can be any extended regular expression.

Solution 3:

Here's a (tested) awk solution, separated onto multiple lines for readability:

awk '/pattern/ {do_print=1}
     do_print==1 {print}  
     NF==0 {do_print=0}' input_file

This script will also print the blank line so it's easier to visually separate the different matched blocks. If you don't want the blank line, swap the 2 lines do_print==1 {print} and NF==0 {do_print=0}

Explanation:

  • awk: invoke the awk tool - it evaluates the input one line at a time sequentially.
  • '...'.: everything enclosed by the single quotes is given to awk as instructions. In this case we perform the quoted instructions on each line.
  • /pattern/ {do_print=1}: whenever a line contains "pattern", turn on the do_print flag
  • do_print==1 {print}: if the do_print flag is set to on, print the current line.
  • NF==0 {do_print=0}: NF stands for Number of Fields. awk delimits each line by spaces and tabs by default to break a line into fields. In this case trivially a blank line has no fields - so we turn off the do_print flag to stop printing when we see a line with NF == 0