来自 Gawk 手册:
当一条规则中的 awk 语句很短时,您可能需要将多个语句放在一行中。这是通过用分号 (';') 分隔语句来完成的。这也适用于规则本身。因此,本节开头所示的程序也可以这样编写:
/12/ { print $0 } ; /21/ { print $0 }
注意:原始 awk 语言中没有规定同一行上的规则必须用分号分隔的要求;添加它是为了与动作中语句的处理保持一致。
但我从https://stackoverflow.com/q/20262869/156458
awk '$2=="no"{$3="N/A"}1' file
$2=="no"{$3="N/A"}
和不是1
两个语句吗?为什么他们没有被任何东西分开?
谢谢。
答案1
非常好的问题!我认为关键在于:“因此,本节开头所示的程序也可以写成这边走:”
不强制必须这样写。这是一种替代方式。这意味着(并已在行动中证明)以下陈述都是正确的:
$ awk '/12/ { print $0 } /21/ { print $0 }' file
$ awk '/12/ { print $0 } ; /21/ { print $0 }' file
我认为这种分号的用法是为了涵盖非常短的惯用代码,例如我们省略操作部分并且我们希望在同一行上应用多个规则的情况:
$ awk '/12//21/' file
awk: cmd. line:2: /12//21/
awk: cmd. line:2: ^ unexpected newline or end of string
在这种情况下,必须使用分号来分隔规则(=条件):
$ awk '/12/;/21/' file
由于该{action}
部分在两个规则/两个条件下都被省略,因此将为每个规则执行默认操作={print $0}
答案2
在 gawk 中,这两个引用从手册描述问题:
一个操作由一个或多个 awk 语句组成,括在大括号 ('{…}') 中。每个语句指定要做的一件事。语句由换行符或分号分隔。
分号是一个“分隔器“但不是”终结者"。
动作的唯一有效终止符是右大括号 ( }
)。
因此,动作右大括号 ( ) 后面}
必须是其他内容模式{动作}
在《男人莫克“还有一些其他描述可能有助于阐明 awk 应该做什么:
语句以换行符、分号或两者都终止。语句组(例如操作或循环体)通过 { ... } 进行阻止,就像在 C 中一样。块中的最后一个语句不需要终止符。
男人诺克”这样解释:
首先是模式,然后是行动。操作语句包含在 { 和 } 中。
而且,如果你想深入了解细节,阅读 POSIX 说明:
action : '{' newline_opt '}'
| '{' newline_opt terminated_statement_list '}'
| '{' newline_opt unterminated_statement_list '}'
;
并搜索什么是“未终止”语句列表。
或者,更简单,搜索行动读书:
任何单个语句都可以替换为括在大括号中的语句列表。应用程序应确保语句列表中的语句由<换行>或<分号>字符分隔。
再次:are separated by <newline> or <semicolon> characters
答案3
条件块之间的分号似乎是可选的;语句之间只有分号之内块似乎是强制性的:
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" } /bar/ {print "bar found"}'
foo found
bar found
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" }; /bar/ {print "bar found"}'
foo found
bar found
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found"; print "whee" }'
foo found
whee
$ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" print "whee" }'
gawk: cmd. line:1: /foo/ { print "foo found" print "whee" }
gawk: cmd. line:1: ^ syntax error
但是,当两个条件之间的实际代码块被省略以支持默认值(即{print}
)时,分号就变得必要:
$ echo -e "foo\nbar" | gawk '/foo/ /bar/'
gawk: cmd. line:2: /foo/ /bar/
gawk: cmd. line:2: ^ unexpected newline or end of string
$ echo -e "foo\nbar" | gawk '/foo/; /bar/'
foo
bar