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.