1

I have a file like this:

text1 text2 Pattern1 text3 text4 Pattern1 text5 text2 text6 Pattern1 text7 text8 Pattern2 text2 text9 text10 text2 Pattern1 text11 text12 Pattern1 text13 text14 Pattern1 text15 text16 Pattern2 text1 text2 Pattern1 text3 text4 Pattern1 text5 text6 Pattern1 text7 text2 text8 Pattern2 text21 text22 

I want to print ONLY

Pattern1 text7 text8 Pattern2 Pattern1 text15 text16 Pattern2 Pattern1 text7 text2 text8 Pattern2 

i.e. if Pattern1 is followed by Pattern2, then print lines between Pattern1 and Pattern2. I don't want lines if Pattern1 is followed by Pattern1.

An awk command is highly appreciated.

I was trying like:

awk '/Pattern1/,/Pattern2' file \> output 

but it gives all the lanes that appear between two successive Pattern1 also.

1

5 Answers 5

1

You may use this awk:

awk ' /^Pattern1$/ {s = $0 ORS; next} s != "" {s = s $0 ORS} /^Pattern2$/ {printf "%s", s; s = ""} ' file Pattern1 text7 text8 Pattern2 Pattern1 text15 text16 Pattern2 Pattern1 text7 text2 text8 Pattern2 
Sign up to request clarification or add additional context in comments.

Comments

1
$ awk ' /Pattern1/,/Pattern2/ { # between the first start and end markers if(/Pattern1/) # at the begin marker... b=$0 # ... reset buffer else b=b ORS $0 # or keep on buffering if(/Pattern2/) # at the end marker... print b # ... it is time to output }' file 

head -4 of output:

Pattern1 text7 text8 Pattern2 ... 

2 Comments

That need to duplicate the start/end "patterns" is why it's best to avoid range expressions, see is-a-start-end-range-expression-ever-useful-in-awk.
@EdMorton My point was to highlight why the provided sample solution as such was not enough to solve the problem. And yes, each such case is unique and /../,/../ kind of makes a rotten stepping stone for each of them - try it, fail with it then do it like it should've been done from the beginning.
1

Making a whole lot of assumptions about unstated requirements like whether to match to the first or last Pattern2, what to do if one or the other is missing from a file,what to do if both "patterns" occur on 1 line, etc.:

$ cat tst.awk /Pattern1/ { f=1; rec="" } f { rec = rec $0 ORS if ( /Pattern2/ ) { printf "%s", rec f = 0 } } 

$ awk -f tst.awk file Pattern1 text7 text8 Pattern2 Pattern1 text15 text16 Pattern2 Pattern1 text7 text2 text8 Pattern2 

See also How do I find the text that matches a pattern?.

Comments

0

If you just want to do it in one gulp, you can use perl:

perl -0777 -nE 'say $1 while (/(^Pattern1$ (?:\R(?!^Pattern2$|^Pattern1$).*)*\R ^Pattern2$)/gmx)' file Pattern1 text7 text8 Pattern2 Pattern1 text15 text16 Pattern2 Pattern1 text7 text2 text8 Pattern2 

Comments

0

This might work for you (GNU sed):

sed -n 'H;/Pattern1/h;/Pattern2/{g;p}' file 

Turn off implicit printing by setting -n.

Append the current line to the hold space (spare buffer).

If the current line contains Pattern1, replace the hold space by this line.

If the current line contains Pattern2, replace the current line by contents of the hold space and print the result.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.