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.