I know how to use the range operator in awk
awk \'/start/,/stop/\' file
Is it possible to select text inside the range operator? ATM, I am usin
Never use a range expression as it makes trivial jobs very slightly briefer but then requires a complete rewrite or duplicate conditions when the task gets slightly more interesting.
Instead of:
awk '/start/,/stop/' file
Use:
awk '/start/{f=1} f{print} /stop/{f=0}' file
and then what you want to do becomes simply:
awk '/start/{f=1} f{ if ($1~/foo/) { } } /stop/{f=0}' file
I'm assuming you have something in mind for inside the empty { }
.
Well what you have proposed does work:
$ seq 1 15 | awk '/^6/,/^9/ { if ($1~/8/){print} else print "in range but not 8" }'
in range but not 8
in range but not 8
8
in range but not 8
But as Ed Morton states, it is a brittle construct.
Example, the ,
is the lowest precedence and you may scratch your head over why this does not work:
$ echo "this one print" | awk '/^1/ , /^55/ || /this/'
Another example. Suppose you have:
$ echo "a
b
c
---
d
e
f
---
g
h"
Try and use a range operator to include or exclude everything between ---
. It is tricky since the start and end marks are the same and it is possible to set and reset a range on the same line.
When if you train you muscle memory to not do /^x/ , /^y/
and instead do /^x/{flag=1} flag{whatever} /^y/{flag=0}
then no more head scratching:
$ echo "this one print" | awk '/^1/{flag=1} flag || /this/{print} /^55/{flag=0}'
this one print
Or,
$ echo "a
b
c
---
d
e
f
---
g
h" | awk '/^---$/{f= ! f; next} f'
d
e
f
(Just change to ! f
at the end if you want to reverse from include to exclude...)
So in general, you can do this for a range and subrange:
awk '/^start/ || /^end/{f= ! f; next} /e/ && f { what you do in sub range }' file
^ ^ can be a single regex if same pattern
^ remove next to include in processing
^ applies to within range /start/,/end/
^ ^ because of the flag