第5.7节:awk赋值运算
1 第5.7节:awk赋值运算
赋值是一种表达式,它会把一个(通常是不同的)值存储到变量中。例如,我们把值 1 赋给变量 z
:
z = 1
执行该表达式后,变量 z
的值为 1 。z
在赋值前的任何旧值都会被丢弃。
赋值操作也可存储字符串值。例如,以下代码会把 "this food is good"
存储到变量 message
中:
thing = "food"
predicate = "good"
message = "this " thing " is " predicate
这也体现了字符串拼接。=
符号被称为赋值运算符。它是最简单的赋值运算符,因为右侧操作数的值会原封不动地存储起来。大多数运算符(加法、拼接等)只有在计算值时才有用;若值不用,使用运算符就没必要。而赋值运算符不同:它会产生一个值(即便你忽略该值),但赋值操作会通过修改变量产生副作用(side effect )。
赋值操作的左侧操作数不一定是变量(见 6.1.3 节《变量》,第 128 页 );也可以是字段(见 4.4 节《修改字段内容》,第 73 页 )或数组元素(见第 8 章《awk 中的数组》,第 181 页 )。这些都被称作左值(lvalues),即它们可出现在赋值运算符左侧。右侧操作数可以是任意表达式;它会生成要存储到指定变量、字段或数组元素里的新值(这类值被称作右值(rvalues) )。
需注意,变量没有固定类型。变量的类型就是最后一次赋给它的值的类型。看下面的程序片段,变量 foo
起初是数值类型,之后变成字符串类型:
foo = 1
print foo
foo = "bar"
print foo
第二次赋值给 foo
字符串值后,它之前的数值类型就被遗忘了。
未以数字开头的字符串值,数值类型为 0 。执行以下代码后,foo
的值为 5 :
foo = "a string"
foo = foo + 5
注意:把变量先当数字用、后当字符串用容易造成混淆,属于不良编程风格。前面两个示例只是说明 awk 的工作机制,并非推荐的编程方式!
赋值是一种表达式,所以它有值——就是被赋的值。比如,z = 1
是一个值为 1 的表达式。由此可衍生出连续赋值写法,像这样:
x = y = z = 5
这个示例会把值 5 存入 x
、y
、z
三个变量。原理是:z = 5
的值为 5 ,会存入 y
;接着 y = z = 5
的值(也是 5 )会存入 x
。
赋值操作可在任何需要表达式的地方使用。例如,编写 x != (y = 1)
来把 y
设为 1 ,然后测试 x
是否等于 1 ,这是合法的。但这种风格往往会让程序难以阅读;除非是在一次性(one-shot )程序中,否则应避免嵌套赋值。
除了 =
,还有几种其他赋值运算符,它们会结合变量的旧值进行算术运算。比如,+=
运算符会把右侧的值加到变量的旧值上,计算出新值。因此,以下赋值操作会把 foo
的值加 5 :
foo += 5
这等价于:
foo = foo + 5
用哪种写法取决于哪种能让程序含义更清晰。
有些情况下,使用 +=
(或任何赋值运算符 )和简单重复左侧操作数在右侧表达式中,结果并不相同。例如:
# 感谢 Pat Rankin 提供此示例
BEGIN {foo[rand()] += 5for (x in foo)print x, foo[x]bar[rand()] = bar[rand()] + 5for (x in bar)print x, bar[x]
}
bar
的下标几乎肯定不同,因为每次调用 rand()
都会返回不同的值。(数组和 rand()
函数尚未讲到。更多信息见第 8 章《awk 中的数组》,第 181 页,以及 9.1.3 节《数值函数》,第 198 页 )。这个示例说明了赋值运算符的一个重要特性:左侧表达式只会求值一次。
至于先对左侧还是右侧表达式求值,由具体实现决定。看下面这个示例:
i = 1
a[i += 2] = i + 1
a[3]
的值可能是 2 ,也可能是 4 。
下表列出了算术赋值运算符。在每种情况下,右侧操作数是一个表达式,其值会被转换为数字。
运算符 | 作用 |
---|---|
lvalue += increment | 将 increment (增量)加到 lvalue 的值上 |
lvalue -= decrement | 从 lvalue 的值中减去 decrement (减量) |
lvalue *= coefficient | 将 lvalue 的值乘以 coefficient (系数) |
lvalue /= divisor | 将 lvalue 的值除以 divisor (除数) |
lvalue %= modulus | 将 lvalue 的值设为其对 modulus (模数)取余的结果 |
lvalue ^= power | 将 lvalue 的值求 power (幂次)次方 |
lvalue **= power | 将 lvalue 的值求 power (幂次)次方(c.e. 可能是特定语境缩写,无特殊说明可忽略 ) |
表 6.2:算术赋值运算符
注意:POSIX 标准仅规定了 ^=
运算符。为实现最大程度的可移植性,请勿使用 **=
运算符。
1.1.1 /=
与正则表达式之间的语法歧义
/=
赋值运算符和首字符为 =
的正则表达式常量之间存在语法歧义。这在一些商业版本的 awk
中尤为明显。例如:
$ awk /==/ /dev/null
<kbd>error</kbd> awk: syntax error at source line 1
<kbd>error</kbd> context is
<kbd>error</kbd> >>> /= <<<
<kbd>error</kbd> awk: bailing out at source line 1
一种变通方法是:
awk '/[=]=/' /dev/null
gawk
不存在此问题;BWK awk 和 mawk
也不存在该问题 。
作者声明:本文用于记录和分享作者的学习心得,可能有部分文字或示例来自AI平台,如:豆包、DeepSeek(硅基流动)(注册链接)等,由于本人水平有限,难免存在表达错误,欢迎留言交流和指教!
Copyright © 2022~2025 All rights reserved.