10

I need to extract particular lines between two matching patterns from a huge file.

Let's say pattern1 (unique in a file) matches a particular line # n and pattern2 (not unique in a file) matches line # m next immediate match after line # n. Then I want to extract all lines between and including line #n to #m

Sample File contents

***************************************************************************
text line # n-2
text line # n-1
********************************* Results *********************************
SUCCEEDED
...
...
some text
***************************************************************************
text line # m+1
text line # m+2
***************************************************************************

Desired Output

********************************* Results *********************************
SUCCEEDED
...
...
some text
***************************************************************************

It would be appreciated if you could help me solve this problem

fedorqui
  • 275,237
  • 103
  • 548
  • 598
jkshah
  • 11,387
  • 6
  • 35
  • 45
  • I marked this question as a duplicate to the one I opened to cover all cases. This way, we have a main place with good explanations on this topic. – fedorqui Mar 27 '17 at 13:28

3 Answers3

24

This can be an approach:

$ awk '/pattern1/ {p=1}; p; /pattern2/ {p=0}' file
********************************* Results *********************************
SUCCEEDED
...
...
some text
***************************************************************************
  • When it finds pattern1, then makes variable p=1.
  • it just prints lines when p==1. This is accomplished with the p condition. If it is true, it performs the default awk action, that is, print $0. Otherwise, it does not.
  • When it finds pattern2, then makes variable p=0. As this condition is checked after p condition, it will print the line in which pattern2 appears for the first time.

If you want an exact match of the lines:

$ awk '$0=="pattern1" {p=1}; p; $0=="pattern2" {p=0}' file

Test

$ cat a
***************************************************************************
text line # n-2
pattern1
********************************* Results *********************************
SUCCEEDED
...
...
some text
***************************************************************************
pattern2
text line # m+2
pattern2
***************************************************************************
$ awk '/pattern1/ {p=1}; p; /pattern2/ {p=0}' a
pattern1
********************************* Results *********************************
SUCCEEDED
...
...
some text
***************************************************************************
pattern2
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Thanks for your response. but I can't match line # n-1 and line # m+1. They are not deterministic – jkshah Oct 04 '13 at 09:39
  • @jkshah oh, now I see. Check my updated answer. I take into account the fact that you are looking for a pattern1, see the test. – fedorqui Oct 04 '13 at 09:44
  • updated ans excludes line #n and #m, which is not desired. Can you please check? It seems your solution in line with what is suggested by @Jotne and it works fine. – jkshah Oct 04 '13 at 09:50
  • It does not exclude line #n and #m. This solution provides a more general approach for you looking for specific pattern1 and pattern2. – fedorqui Oct 04 '13 at 09:53
  • I substituted `Results` for `pattern1` and `^[*]+$` for `pattern2` and it removed starting and ending lines. Am I doing something worg? bdw +1 for your explanations – jkshah Oct 04 '13 at 09:56
  • Ok, I was getting confused with the fact of printing `n` or `n+1`. Now I turned the condition so both lines are printed: the one with `pattern1` and the first with `pattern2`. Hope it is clear now :) – fedorqui Oct 04 '13 at 10:02
  • 1
    Now that's perfect and concise. Thanks a lot! – jkshah Oct 04 '13 at 10:11
8

Using sed:

$ sed '/start_pattern_here/,/end_pattern_here/!d' inputfile

and in OP's specific case:

$ sed '/[*]* Results [*]*/,/^[*]*$/!d' inputfile
********************************* Results *********************************
SUCCEEDED
...
...
some text
***************************************************************************

Assuming that the unique pattern was *** Results *** and the non-unique one was ********.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
devnull
  • 118,548
  • 33
  • 236
  • 227
1

Using awk

awk '/Result/ {p=1;print;next}  /^\*\*\*\*\*/ && p {p=0;print} p' file
********************************* Results *********************************
SUCCEEDED
...
...
some text
***************************************************************************
Jotne
  • 40,548
  • 12
  • 51
  • 55