Blog

Grep - finding a line but displaying a different one

Naturally, on Linux, you use the grep command to search through text files. I’m so used to it that I basically run it on autopilot. But that’s not entirely fair, because it’s got some pretty cool features to offer.

Recently, I was digging through some app logs where each entry spans three lines, and I needed to display a different line than the one matching the regular expression. Normally, I’d whip up a quick bash script to handle it, but—guided by StackOverflow, of course—I stumbled across a simple and effective solution.

Grep has these handy line context flags, like:

-A NUM, --after-context=NUM
Print  NUM  lines  of  trailing  context after matching lines.  
Places a line containing a group separator (--) between contiguous groups of matches.  
With the -o or --only-matching option, this has no effect and a warning is given.

-B NUM, --before-context=NUM
Print NUM lines of leading context before matching lines. 
Places a line containing a group separator (--) between contiguous groups of matches.  
With the -o or --only-matching option, this  has  no  effect  and  a warning is given.

-C NUM, -NUM, --context=NUM
Print NUM lines of output context.  
Places a line containing a group separator (--) between contiguous groups of matches.  
With the -o or --only-matching option, this has no effect and a warning is given.

Each of these parameters separates the results with a double dash.

Since a picture is worth a thousand words, let’s dive into some simple examples.

For a sample file:

2021-12-01
line A 1
line A 2
line A 3
2021-12-01
line B 1
line B 2
line B 3
2021-12-02
line C 1
line C 2
line C 3
2021-12-02
line D 1
line D 2
line D 3

I’m translating and explaining:

Case one with the -A parameter: we’re interested in the content of the second line after the date December 2, so:

$grep 12-02 -A2 grep.txt
2021-12-02
line C 1
line C 2
--
2021-12-02
line D 1
line D 2

Case two with the -B parameter: we’re interested in the content of the line one position above the line containing the digit "2":

$ grep 'line.*2' -B1 grep.txt
line A 1
line A 2
--
line B 1
line B 2
--
line C 1
line C 2
--
line D 1
line D 2

Case three with the -C parameter: it combines the -A and -B parameters and displays the content of the lines before and after by the specified amount. Note that if the results overlap, the lines don’t get duplicated, so:

$ grep 'line.*2' -C2 grep.txt
2021-12-01
line A 1
line A 2
line A 3
2021-12-01
line B 1
line B 2
line B 3
2021-12-02
line C 1
line C 2
line C 3
2021-12-02
line D 1
line D 2
line D 3

It will display the entire file—without separators—because two lines up and down from the results, there’s nothing beyond what’s already visible.

Thanks for your attention.