Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a pattern range match that is multi-line and non-greedy?

Tags:

regex

bash

I am trying to pull a bash one-liner for printing lines between two patterns. I need it to be non-greedy, though. I have a file 'test.txt' that contains the following:

############ Apple ############
# 1
# 2
# 3
# 4      
#################################

############ Orange ############
# 1
# 2
# 3
# 4
#################################

############ Grape ############
# 1
# 2
# 3
# 4      
#################################

What I want to be printed is the "Orange" section. And ONLY that section. That is, I want the following printed:

############ Orange ############
# 1
# 2
# 3
# 4
#################################

I also do not want to match for a specific number of lines, as the line count will fluctuate. I have tried a bunch of different things. I have tried sed, awk, grep (with -P and *.? regex). Nothing seems to fit the bill here. Sed and awk are greedy, so I can't match the end of the section. Grep (as far as I can tell) doesn't support multi-line range matching. Is there a solution to this using built-ins? I know that there is pcregrep, but I'd rather use built-ins or something that "ships" with common distros. I'm going for "out-of-the-box" and elegant. Is it possible?

like image 373
earth Avatar asked Mar 21 '23 04:03

earth


1 Answers

Use an address range with sed:

sed -n '/^#\+[ ]*Orange[ ]*#\+/,/^#\+$/ p' infile

It yields:

############ Orange ############
# 1
# 2
# 3
# 4
#################################
like image 159
Birei Avatar answered Apr 05 '23 21:04

Birei