`!a[$0]++` 的 awk 运算符优先级

`!a[$0]++` 的 awk 运算符优先级

我有一个 awk 表达式!a[$0]++,我想知道确切的求值顺序。从 awk 的文档来看,++的优先级高于!.然而,在这个例子中,++是 的后缀形式(不是!++a[$0],据我了解,它基本上告诉 awk,“首先评估其他部分,然后评估我”。在这种情况下,评估顺序是什么?

答案1

我想我们可以同意a[$0]在这里具有最高优先级(*),所以我们可以将其简化为x

我要说你读到的内容是正确的,它的++优先级高于!,所以这些应该是相等的:

$ awk 'BEGIN{ x=123; tmp = !x++;  print tmp, x; }'
0 124
$ awk 'BEGIN{ x=123; tmp = !(x++);  print tmp, x; }'
0 124

确实如此。!x++获取 的值x,返回它并随后递增。返回值123被取反,产生0。稍后可以在 中找到增加的值x

但我们也尝试一下另一种可能性,这种可能性!结合得更紧密:

$ awk 'BEGIN{ x=123; tmp = (!x)++;  print tmp, x; }'
awk: cmd. line:1: BEGIN{ x=123; tmp = (!x)++;  print tmp, x; }
awk: cmd. line:1:                           ^ syntax error

嗯,哎呀。现在,这是行不通的,因为!首先会取 的值x,然后对其取反,返回0。现在++应该增加它,并将结果存储回来。但0它只是一个值,而不是一个变量,它不能被存储。因此出现了错误。 (类似的东西(1+2)++会给出同样的错误。)

因此,++具有更高的优先级,它只是有一个隐藏的副作用,从它返回的值来看并不明显。

(* 订阅运算符不会出现在优先级表在标准中,与C的运算符优先级表,但如果它的优先级较低,则该表达式实际上不起作用。)

答案2

演示:

$ cat file
1 a
2 b
1 c
2 d
3 e
$ awk '!a[$1]++' file
1 a
2 b
3 e

++首先发生。由于它是后递增,因此对于第一行,a[$1]++递增 a[1] 的值但返回零,并且求反将其翻转为 true,然后打印第一行。与第 2 行相同。对于第三行,a[1]已经有值1,后置增量将值设置为2并返回1,其取反为假。


mawk 手册页更清晰:

   New expressions are composed with the following operators in order of increasing
   precedence.

        assignment          =  +=  -=  *=  /=  %=  ^=
        conditional         ?  :
        logical or          ||
        logical and         &&
        array membership    in
        matching       ~   !~
        relational          <  >   <=  >=  ==  !=
        concatenation       (no explicit operator)
        add ops             +  -
        mul ops             *  /  %
        unary               +  -
        logical not         !
        exponentiation      ^
        inc and dec         ++ -- (both post and pre)
        field               $

相关内容