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
something like this works for me:
file.awk:
BEGIN {
record=0
}
/^abc$/ {
record=1
}
/^mno$/ {
record=0;
print "s="s;
s=""
}
!/^abc|mno$/ {
if (record==1) {
s = s"\n"$0
}
}
using: awk -f file.awk data
...
edit: O_o fedorqui solution is way better/prettier than mine.
I tried to use awk
to print lines between two patterns while pattern2 also match pattern1. And the pattern1 line should also be printed.
e.g. source
package AAA
aaa
bbb
ccc
package BBB
ffffd
eee
package CCC
fff
ggg
hhh
iii
package DDD
jjj
should has an ouput of
package BBB
ffffd
eee
Where pattern1 is package BBB
, pattern2 is package \w*
. Note that CCC
isn't a known value so can't be literally matched.
In this case, neither @scai 's awk '/abc/{a=1}/mno/{print;a=0}a' file
nor @fedorqui 's awk '/abc/{a=1} a; /mno/{a=0}' file
works for me.
Finally, I managed to solve it by awk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' file
, haha
A little more effort result in awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' file
, to print pattern2 line also, that is,
package BBB
ffffd
eee
package CCC
From the previous response's links, the one that did it for me, running ksh
on Solaris, was this:
sed '1,/firstmatch/d;/secondmatch/,$d'
1,/firstmatch/d
: from line 1 until the first time you find firstmatch
, delete./secondmatch/,$d
: from the first occurrance of secondmatch
until the end of file, delete.perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file
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 the flag
when the text abc
is found. Then, it skips the line. /mno/{flag=0}
unsets the flag
when the text mno
is found.flag
is a pattern with the default action, which is to print $0
: if flag
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?.
sed '/^abc$/,/^mno$/!d;//d' file
golfs two characters better than ppotong's {//!b};d
The empty forward slashes //
mean: "reuse the last regular expression used". and the command does the same as the more understandable:
sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file
This seems to be POSIX:
If an RE is empty (that is, no pattern is specified) sed shall behave as if the last RE used in the last command applied (either as an address or as part of a substitute command) was specified.