How to get the n-th line after a grepped one?
There is nothing wrong with the previous two answers, but I thought I would make you aware that finding the third line after a pattern can be done in a single sed
call:
sed -n "/four/ { n; n; p }" SourceData.txt
Because a single program does the work, this is more efficient than running multiple filters. The above command outputs the third line after every instance of "four", except where this occurs again in one of the two lines following a match (the other solutions don't handle this case in the expected manner either); also, no output is generated if the pattern is in the last or second-last line of the file, which may or may not be what you want.
To match the first instance only:
sed -n "/four/ { n; n; p; q }" SourceData.txt
(Note that this answer is as efficient as possible, by ending the scan as soon as the match is found.)
I add this solution because it is worth getting to know sed
and, despite its rather off-putting syntax (regular expressions are bad enough!), it can often be extremely useful. This tutorial is a good introduction.
Note: this answer was originally written before the OP clearly stated the pattern appears just once. It is designed not to miss any occurrence (unless near the end, so there's no "n-th line after") and I'm going to leave it this way. If you're sure there's only one occurrence or if you want only the first one to be found, you may consider some other solution that stops immediately and doesn't parse the whole input stream/file in vain.
This solution prints the current line iff there was a match two lines ago. It is slightly different from few other answers because it won't miss another match even if it occurs soon after the previous match.
awk -v delay=2 '{for (i=delay; i>=0; i--) t[i]=t[i-1]} /four/ {t[0]="m"} {if (t[delay]) print}'
Whenever there's a match, the information is stored in t[0]
. With each line the t
array is shifted (including shifting t[-1]
to t[0]
to reset the value of t[0]
). The line is printed iff the array indicates there was a match two lines ago.
You can easily set a different delay (e.g. delay=7
) or use another pattern (e.g. /sda[[:digit:]]/
)
You can use this expression (input.txt
):
grep "four" -A 2 input.txt | tail -n 1
Output is:
six 6
The grep
option "-A 2" states that two lines after the matched line are outputted.
And the tail
option "-n 1" states that only the last 1
lines of this result are returned.