5

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.

Zhilong Jia
  • 2,329
  • 1
  • 22
  • 34

3 Answers3

7

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.

Kent
  • 189,393
  • 32
  • 233
  • 301
  • `awk '/start/,/end/{next}1'` correct and detailed answer for my question, though I havenot explain it clearly using this awkward example! – Zhilong Jia Apr 12 '13 at 04:18
1

Is sed an alternative?

$ sed '/#/,/#/d' input
abd
hfdh
end
Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
1

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.

twalberg
  • 59,951
  • 11
  • 89
  • 84
  • this won't work for OP's example, it has same start and end patterns. You need check the `x` not only for printing, but also for setting `x` itself. – Kent Apr 11 '13 at 17:32
  • @Kent good catch... edited in an alternative version that takes that into account. – twalberg Apr 11 '13 at 18:17