Print line X lines before/after found line

Solution 1:

grep will do this for you, with options -A (after) and -B (before), and -C (context). An example I often use is:

   sudo lspci -vnn | grep -i net -A 12

because this command will show 12 lines after the match, which includes the driver used to control the network (-i net) card. In general, the command is:

  grep text_to_search -A n -B m file.extension

which will output m lines before the match, and n lines after the match. Or you can use

 grep text_to_search -C n file.extension

to show a total of n lines surrounding the text found (half before, half after the match).

Solution 2:

After looking into this question a little bit I think I have to revise my comment about the feasability using standard GNU tools without scripting. This may be very hard to do because of the special cases.

If you don't mind using awk I could offer the following solution. This script context.awk ist still rather concise:

{
    lines[NR] = $0
    if (dump[NR]) {
        print $0;
    if ($0 ~ Pattern) {
        if (NR-Delta in lines) {
            print "---"
            print lines[NR-Delta]
        }
        dump[NR+Delta] = 1
        print $0;
    }
    if (NR-Delta in lines) 
        delete lines [NR-Delta];
}

It has to be called as follows:

awk -v Delta=X -v Pattern=PATTERN -f context.awk sample.txt

where X is the desired "context distance" and PATTERN the search pattern. The script tries to seperate multiple pattern contexts in the file by printing lines with --- in between. So, for example, the following sample.txt

line1
line2
line3 XXX
line4
line5
line6
line7 XXX
line8
line9
line10 XXX
line11

using this call

awk -v Delta=3 -v Pattern=XXX -f context.awk sample.txt

will yield the followng output

line3 XXX
line6
---
line4
line7 XXX
line10 XXX
---
line7 XXX
line10 XXX