我知道如何在awk中使用范围运算符
awk '/start/,/stop/' file
是否可以在范围运算符中选择文本? ATM,我正在使用if语句
awk '/start/,/stop/ { if ($1~/foo/) { } }' file
是否有一种更为自觉的方式呢?
答案 0 :(得分:1)
永远不要使用范围表达式,因为它使得琐碎的工作变得非常简单,但是当任务变得更有趣时,需要完全重写或复制条件。
而不是:
awk '/start/,/stop/' file
使用:
awk '/start/{f=1} f{print} /stop/{f=0}' file
然后您想做的事情变得简单:
awk '/start/{f=1} f{ if ($1~/foo/) { } } /stop/{f=0}' file
我假设你在空{ }
内有一些想法。
答案 1 :(得分:1)
你提出的建议确实有效:
$ 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
但正如埃德莫顿所说,这是一个脆弱的结构。
例如,,
是最低优先级,您可能会因为这不起作用而不知所措:
$ echo "this one print" | awk '/^1/ , /^55/ || /this/'
另一个例子。假设你有:
$ echo "a
b
c
---
d
e
f
---
g
h"
尝试使用范围运算符来包含或排除---
之间的所有内容。它是tricky,因为起始和结束标记是相同的,并且可以set and reset在同一行上的范围。
如果你训练你的肌肉记忆不能/^x/ , /^y/
,而是做/^x/{flag=1} flag{whatever} /^y/{flag=0}
,那么就不再有头疼了:
$ echo "this one print" | awk '/^1/{flag=1} flag || /this/{print} /^55/{flag=0}'
this one print
或者,
$ echo "a
b
c
---
d
e
f
---
g
h" | awk '/^---$/{f= ! f; next} f'
d
e
f
(如果您想要从包含排除到排除,只需在结尾处更改为! f
。)
因此,一般来说,您可以对范围和子范围执行此操作:
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