sed

Extract nth or last occurence of a block of lines between two expressions of a file using sed


Input file:

1
2
start pattern
3
4   - 1st block
5
end pattern
6
7
.
.
start pattern
20
21     - nth block
22
end pattern
.
.
start pattern
27
28     - last block
29
end pattern
30
31

I'm trying to extract the blocks along with start pattern and end pattern, which I'm able to get using below sed expression

sed '/start_pattern/,/end_pattern/!d' inputfile

Output file:

start pattern
3
4   - 1st block
5
end pattern
start pattern
20
21     - nth block
22
end pattern
start pattern
27
28     - last block
29
end pattern

But I just want a specific block, in current case last block (using sed only)

Required output:

start pattern
27
28     - last block
29
end pattern

Also Is it possible to get specific occurrence other than first or last, if so how.?


The question is similar to the below questions but with different requirements.

How to select lines between two marker patterns which may occur multiple times with awk/sed

How to select lines between two patterns?


Solution

  • This might work for you (GNU sed):

    sed '/start/,/end/!d;/end/q' file # first occurrence only
    
    sed '/start/h;//!H;$!d;x;s/^\(start.*end[^\n]*\).*/\1/p;d' file # last only
    
    sed '/start/!d;x;s/^/x/;/x\{10\}/!{x;d};x;:a;n;/end/!ba;q' file # 10th only
    

    This first quits after the first range match.

    The last stores the last range match in the hold space and at end of file prints it out.

    The nth stores a counter in the hold space and when it matches the required number, prints out the next range and quits.