Printing all contents EXCEPT matching range patter

2019-02-18 02:20发布

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)?

e.g.

$cat 1.t

abd
hfdh
#  
fafa
deafa
123 
#
end

the result I wanted:

cat 1.t

abd
hfdh
end

EDIT:

I gave an impertinent example. the endpattern should be different with the startpattern because I just have not test this. That's My fault.

At the same time, I want to operate the range pattern and the not range pattern differently. So sed is not my choice.

3条回答
在下西门庆
2楼-- · 2019-02-18 02:40

Is sed an alternative?

$ sed '/#/,/#/d' input
abd
hfdh
end
查看更多
神经病院院长
3楼-- · 2019-02-18 02:50

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.

查看更多
贪生不怕死
4楼-- · 2019-02-18 02:51

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.

查看更多
登录 后发表回答