How to select lines between two marker patterns which may occur multiple times with awk/sed
Using awk
or sed
how can I select lines which are occurring between two different marker patterns? There may be multiple sections marked with these patterns.
For example: Suppose the file contains:
abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu
And the starting pattern is abc
and ending pattern is mno
So, I need the output as:
def1
ghi1
jkl1
def2
ghi2
jkl2
I am using sed to match the pattern once:
sed -e '1,/abc/d' -e '/mno/,$d' <FILE>
Is there any way in sed
or awk
to do it repeatedly until the end of file?
Solution 1:
Use awk
with a flag to trigger the print when necessary:
$ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
def1
ghi1
jkl1
def2
ghi2
jkl2
How does this work?
-
/abc/
matches lines having this text, as well as/mno/
does. -
/abc/{flag=1;next}
sets theflag
when the textabc
is found. Then, it skips the line. -
/mno/{flag=0}
unsets theflag
when the textmno
is found. - The final
flag
is a pattern with the default action, which is toprint $0
: ifflag
is equal 1 the line is printed.
For a more detailed description and examples, together with cases when the patterns are either shown or not, see How to select lines between two patterns?.
Solution 2:
Using sed
:
sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'
The -n
option means do not print by default.
The pattern looks for lines containing just abc
to just mno
, and then executes the actions in the { ... }
. The first action deletes the abc
line; the second the mno
line; and the p
prints the remaining lines. You can relax the regexes as required. Any lines outside the range of abc
..mno
are simply not printed.
Solution 3:
This might work for you (GNU sed):
sed '/^abc$/,/^mno$/{//!b};d' file
Delete all lines except for those between lines starting abc
and mno