2

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?

Community
  • 1
  • 1
Hemanth
  • 159
  • 1
  • 12
  • 1
    Are the "first occurrence", "nth occurrence" and "last occurrence" lines your annotation of the input file? If so, can you [edit] the question to show *real* input and expected output? In a [mcve]? – Benjamin W. Mar 07 '17 at 03:29
  • awk would be more suitable for a generic nth occurrence, last occurrence can be either saved and printed at end of file or input file reversed using tac, get 1st occurrence and then reverse the output again... see https://stackoverflow.com/questions/38972736/how-to-select-lines-between-two-patterns – Sundeep Mar 07 '17 at 04:08
  • @BenjaminW. I've updated the question with verifiable output.. Thanks for pointing out.! – Hemanth Mar 07 '17 at 06:54
  • @Sundeep I couldn't find how to get a specific block in the linked question. Can you give the answer in this question..? – Hemanth Mar 07 '17 at 07:00
  • the link was for getting start-end blocks with awk, you need to change to it suit your needs... my suggestion is that awk is better choice than sed here... give it a shot – Sundeep Mar 07 '17 at 07:10

1 Answers1

3

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.

potong
  • 55,640
  • 6
  • 51
  • 83
  • 1
    Nice ones... If GNU sed, maybe you could avoid escaped parenthesis and braces by using `-r` mode. – SLePort Mar 07 '17 at 06:55
  • @potong, Thanks a lot, it worked like charm.. Although I've had to tweak it a little to accommodate my pattern variable; But it is a lot of taking time to return the output – Hemanth Mar 07 '17 at 10:13