In Awk, the range pattern is not an expression, so canot use the \"!\" to not it. so how to implement it (Printing all contents EXCEPT matching range pattern using awk)?
you just gave a tricky (I don't know I should call it good or bad ^_^ ) example. Your text have exactly same startpattern
and endpattern
(#
)
I guess you are looking for the same way as sed '/#/,/#/d'
or sed -n '/#/,/#/!p'
There is some similiar (not same as sed's) address model in awk. In man page there is explanation. I said not same, your example is good one. if start == end
the address model for awk won't work:
kent$ echo "abd
hfdh
#
fafa
deafa
123
#
end"|awk '/#/,/#/{next}1'
abd
hfdh
fafa
deafa
123
end
because awk matches the same line (again check man page) but if they are different, see this example:
kent$ echo "abd
hfdh
#
fafa
deafa
123
##
end"|awk '/#/,/##/{next}1'
abd
hfdh
end
it will give what you want. so if this is the case, you could just do:
awk '/start/,/end/{next}1'
yes, quite similar as sed's one.
If the start and end are really same, you want to do it with awk, you need flag.
kent$ echo "abd
hfdh
#
fafa
deafa
123
#
end"|awk '/#/&&!f{f=1;next}f&&/#/{f=0;next}!f'
abd
hfdh
end
well, in example better use ^#$
, but that is not the point. I hope this answers your question.
If you really need to use awk
, something like this should work:
awk 'BEGIN{x=1} /startpattern/{x=0} /endpattern/{x=1;next} x{print}'
Although the sed
alternative might be a simpler approach (it's less typing, at least).
Edit: @Kent pointed out you have the same start and end pattern, which makes it a bit more tricky, but this should work:
awk 'BEGIN{x=1} /pattern/{x=!x;next} x{print}'
That basically toggles x
every time it sees the pattern, and only prints when x!=0
. The next
in there avoids printing the pattern when it's turning printing back on.
Is sed an alternative?
$ sed '/#/,/#/d' input
abd
hfdh
end