sed/awk - print text between patterns spanned across multiple lines

awk, bash, sed

Solution

You have the right idea, a mini-state-machine in `awk` but you need some slight mods as per the following transcript:

pax> echo 'Hi I would like
to print text
between these 
patterns ' | awk '
    /patterns/ { echo = 0 }
    /Hi /      { gsub("^.*Hi ", "", $0); echo = 1 }
               { if (echo == 1) { print } }'

Or, in compressed form:

awk '/patterns/{e=0}/Hi /{gsub("^.*Hi ","",$0);e=1}{if(e==1){print}}'

The output of that is:

I would like
to print text
between these 

as requested.

The way this works is as follows. The `echo` variable is initially `0` meaning that no echoing will take place.

Each line is checked in turn. If it contains `patterns`, echoing is disabled.

If it contains `Hi` followed by a space, echoing is turned on and `gsub` is used to modify the line to get rid of everything up to the `Hi`.

Then, regardless, the line (possibly modified) is echoed when the `echo` flag is on.

Now, there's going to be edge cases such as:

- lines containing two occurrences of `Hi`; or

- lines containing something before the `patterns`.

You haven't specified how they should be handled so I didn't bother, but the basic concept should be the same.

Problem

I am new to scripting and was trying to learn how to extract any text that exists between two different patterns. However, I am still not able to figure out how to extract text between two patterns in the following scenario: If I have my input file reading: ``` Hi I would like to print text between these patterns ``` and my expected output is like: ``` I would like to print text between these ``` i.e. my first search pattern is "Hi' and skip this pattern, but print everything that exists in the same line following that matched pattern. My second search pattern is "patterns" and I would like to completely avoid printing this line or any lines beyond that. I tried the following: ``` sed -n '/Hi/,/patterns/p' test.txt ``` [output] ``` Hi I would like to print text between these patterns ``` Next, I tried: ``` `awk ' /'"Hi"'/ {flag=1;next} /'"pattern"'/{flag=0} flag { print }'` test.txt ``` [output] ``` to print text between these ``` Can someone help me out in identifying how to achieve this? Thanks in advance

Original source