当前位置: 首页 > news >正文

第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 存入 xyz 三个变量。原理是: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 += incrementincrement(增量)加到 lvalue 的值上
lvalue -= decrementlvalue 的值中减去 decrement(减量)
lvalue *= coefficientlvalue 的值乘以 coefficient(系数)
lvalue /= divisorlvalue 的值除以 divisor(除数)
lvalue %= moduluslvalue 的值设为其对 modulus(模数)取余的结果
lvalue ^= powerlvalue 的值求 power(幂次)次方
lvalue **= powerlvalue 的值求 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.

http://www.dtcms.com/a/341218.html

相关文章:

  • IPSEC安全基础
  • Qt 中最经典、最常用的多线程通信场景
  • TDengine IDMP 运维指南(数据导入导出)
  • WIN10/WIN11:无法下载所有必需的文件 0x80072EE2 0x20000(未解决)
  • C++ std::sort的应用总结
  • Unity 大量子弹和小怪碰撞检测优化
  • GSPO:Towards scalable reinforcement learning for language models
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型和EasyOCR实现汽车牌照动态检测和识别(C#代码,UI界面版)
  • 使用UUP dump制作windows preview镜像
  • 手机、汽车如何实现卫星直连
  • imx6ull-驱动开发篇31——Linux异步通知
  • 玩转QEMU硬件模拟器 - Raspberry Pi OS驱动开发
  • 【项目复盘】【四轴飞行器设计】驱动开发部分
  • Redis 安装教程
  • 【数据结构之二叉树】
  • 【openssl】openssl CA.pl 签发证书操作步骤
  • redis执行lua脚本的原子性和数据库原子性的区别
  • [激光原理与应用-315]:光学设计 - SolidWorks, 光机系统设计的神器,打通光学与机械设计的闭环
  • Tomcat部署与HTTP协议详解
  • 佳维视工业一体机在公共交通系统配套中的应用
  • 疯狂星期四文案网第45天运营日记
  • LTspice仿真电路:(三十五)LED恒流驱动仿真(LT3497)
  • burpsuite+captcha-killer插件识别图片验证码进行爆破
  • AiPy 文档自动化处理实践:从 docx 到结构化 db 的高效转换方案
  • 华为仓颉语言的class(类)初步
  • ES Modules +案例分析
  • 【C++】动态导入Windows系统API的简单方法
  • Docker复杂安装--最详细的MySQL主从复制与Redis集群安装、主从复制、主从扩容主从缩容实战版
  • 03-dockerfile
  • 8月7日国赛全真模拟!2025“华数杯”数学建模竞赛,常用模型及算法总结