awk编程?let‘s go(五) ---- 动作

21 篇文章 1 订阅
8 篇文章 0 订阅

动作

在一个 模式–动作 语句中, 模式决定动作什么时候执行。有时候动作会非常简单: 一条单独的打印语句或赋值语句. 在有些时候, 动作有可能是多条语句, 语句之间用换行符或分号分开。

表达式

表达式是最简单的语句, 大多数其他语句都是由不同类型的表达式组合而成。
初等表达式是最原始的构造块: 它们包括常量, 变量, 数组引用, 函数调用, 以及各种内建变量, 例如字段的名字。

常量

Awk 中只有两种类型的常量: 字符串与数值. 将一个字符序列用一对双
引号包围起来就创建了一个字符串常量,如 “hello”。
一个数值常量可以是一个整数, 就像 1127, 或十进制小数, 3.14等。

变量

表达式可以包含若干种类型的变量: 用户定义的, 内建的, 或字段. 用户定义的变量名字由数字, 字母与下划线构成, 但是名字不能以数字开始. 所有内建变量的名字都只由大写字母组成。
每一个变量都有一个值, 这个值可以是字符串或数值, 或两者都是. 因为变量的类型不需要事先声明, 所以 awk 需要根据上下文环境推断出变量的类型。

内建变量

内建变量属于 awk 本身就内置的变量,可以直接拿来使用。这些变量可以用在所有的表达式中, 而且可以被用户重置。每当有一个新的文件被读取, FILENAME 就会被重新赋值. 每当有一个新的记录被读进来, FNR,NF, NR 就会被重新赋值。

字段变量

当前输入行的字段从 $1, $2, 一直到 $NF; $0 表示整行.。字段变量与其他变量相比没什么不同 — 它们也可以用在算术或字符串运算中, 也可以被赋值。

内建变量表

变量含义默认值
ARGC命令行参数的个数-
ARGV命令行参数数组-
FILENAME当前输入文件名-
FNR当前输入文件的记录个数-
FS控制着输入行的字段分割符" "
NF当前记录的字段个数-
NR到目前为止读的记录数量-
OFMT数值的输出格式“%.6g”
OFS输出字段分割符" "
ORS输出的记录的分割符“\n”
RLENGTH被函数 match 匹配的字符串的长度-
RS控制着输入行的记录分割符“\n”
RSTART被函数 match 匹配的字符串的开始
SUBSEP下标分割符“\034”
算术运算符

Awk 提供了通常的 +, -, *, /, %, ^ 运算符. 运算符 %计算余数: x%y 的值是 x 被 y 除的余数; 当 x 或 y 是负数时, x%y 的结果依赖于机器。^ 是指数运算符: x^y 表示 xy。所有的算术运算都用的是浮点数。

比较运算符

比较表达式指的是那些含有关系运算符, 或含有正则表达式匹配运算符的表达式。 关系运算符包括 <, <=, == (相等), != (不相等), >= 与 >。

表达式

  1. 初等表达式包括:
    数值与字符串常量, 变量, 字段, 函数调用, 数组元素.
  2. 可以把表达式组合起来的运算符包括:
    赋值运算符 = += -= *= /= %= ^=
    条件表达式 ?:
    逻辑运算符 || (OR), && (AND), ! (NOT)
    匹配运算符 ~ 和 !~
    关系运算符 < <= == != > >=
    拼接运算符 (没有显式的拼接运算符)
    算术运算符 + - * / % ^
    单目运算符 + 和 -
    自增与自减运算符 ++ 和 – (包括前缀与后缀)
    括号 (用于分组)
自增与自减

赋值语句:

n = n + 1

通常写成 ++n 或 n++, 这里用到了一元自增运算符, 作用是给变量加 1. 前缀形式 ++n 在传递 n 的值之前为 n 加 1; 后缀形式 n++ 在传递 n 的值之后, 为 n 加 1. 当 ++ 应用到赋值表达式时, 这会造成一些不一样的地方. 如果 n 的初始值为 1, 赋值语句 i = ++n 为 n 加 1, 并将新值 2 赋给i, 而 i = n++ 同样为 n 加 1, 但将旧值 1 赋给 i. 如果仅仅是给 n 加 1, 那么 n++ 与 ++n 没什么区别. 前缀与后缀自减运算符 – 给变量减 1, 除此之外与 ++ 相同。

内建算术函数

内建函数同内建变量一样,可以直接使用,这些函数都可以作为初等表达式使用。

内建算术函数表

函数返回值
atan2(y,x)y/x 的反正切值, 定义域在 −π 到 π 之间
cos(x)x的余弦值, x 以弧度为单位
int(x)x的整数部分; 当 x 大于 0 时, 向 0 取整
log(x)x的自然对数 (以 e 为底)
rand()返回一个随机数 r, 0 ≤ r < 1
sin(x)x 的正弦值, x 以弧度为单位.
sqrt(x)x 的方根
srand(x)x 是 rand() 的新的随机数种子
字符串运算符

Awk 中只有一种字符运算符 — 拼接. 拼接并没有显式的运算符, 通过陆续写出字符串常量, 变量, 数组元素, 函数返回值, 与其他表达式, 就可以创建一个字符串。

内建字符串函数

没见字符串函数用来操作字符串,对应函数表如下:

内建字符串函数表

函数描述
gsub(r,s)将 $0 中所有出现的 r 替换为 s, 返回替换发生的次数.
gsub(r,s,t )将字符串 t 中所有出现的 r 替换为 s, 返回替换发生的次数
index(s,t)返回字符串 t 在 s 中第一次出现的位置, 如果 t 没有出现的话, 返回 0.
length(s)返回 s 包含的字符个数
match(s,r)测试 s 是否包含能被 r 匹配的子串, 返回子串的起始位置或 0; 设置 RSTART 与 RLENGTH
split(s,a)用 FS 将 s 分割到数组 a 中, 返回字段的个数
split(s,a,fs)用 fs 分割 s 到数组 a 中, 返回字段的个数
sprintf(fmt,expr-list)根据格式字符串 fmt 返回格式化后的 expr-list
sub(r,s)将 $0 的最左最长的, 能被 r 匹配的子字符串替换为 s, 返回替换发生的次数.
sub(r,s,t)把 t 的最左最长的, 能被 r 匹配的子字符串替换为 s, 返回替换发生的次数.
substr(s,p)返回 s 中从位置 p 开始的后缀.
substr(s,p,n)返回 s 中从位置 p 开始的, 长度为 n 的子字符串
表达式运算符

将运算符应用到常量, 变量, 字段, 数组元素, 函数, 和其他表达式中, 就可以构造出一个表达式,运算符按照优先级的升序排列. 优先级高的运算符优先求值,常用的表达式运算符总结如下:

表达式运算符表

操作运算符示例含义
赋值= += -= *= /= %= ^=x *= 2x = x * 2
条件表达式?:x ? y : z若 x 为真, 则 y, 否则 z
逻辑或||x || y若 x 或 y 为真, 则为 1, 否则为 0
逻辑与&&x && y若 x 与 y 都为真, 则为 1, 否则为 0
数组成员ini in a如果 a[i] 存在, 则为 1, 否则为 0
匹配~ !~$1 ~ /x/如果第一个字段包含 x, 则为 1, 否则为 0
关系运算< <= == != >= >x == y如果 x 等于 y, 则为 1, 否则为 0
拼接“a” “bc”“abc”; 不存在显式的拼接运算符
减法, 加法+ -x + yx 与 y 的和
乘法, 除法, 取模* / %x % yx 除以 y 的余数
单目加, 单目减+ --xx 的相反数
逻辑非!!$1若 $1 为空或为 0, 则为 1, 否则为 0
指数运算^x ^ yx的y次方的值
自增, 自减++ –++x, x++为 x 加 1
字段$$i+11 加上第 i 个字段的值
组合( )($i)++给第 i 个字段的值加 1
流程控制语句

Awk 提供花括号用于语句组合, if-else 用于决策, while, for, do 语句用于循环。

流程控制语句

  1. {statements}
    语句组
  2. if (expression)statements
    如果 expression 为真, 执行 statements
  3. if (expression) statements1 else statements2
    如果 expression 为真, 执行 statements1, 否则执行 statements2
  4. while (expression) statements
    如果 expression 为真, 执行 statements; 然后重复前面的过程
  5. for (expression1;expression2;expression3 ) statements
    等价于 expression1; while (expression2) { statements; expression3}
  6. for (variable in array) statements
    轮流地将 variable 设置为 array 的每一个下标, 并执行 statements
  7. do statements while (expression)
    执行 statements; 如果 expression 为真就重复
  8. break
    马上离开最内层的, 包围 break 的 while, for 或 do
  9. continue 开始最内层的, 包围 continue 的 while, for, 或 do 的下一次循环
  10. next
    开始输入主循环的下一次迭代
  11. exit
  12. exit expression
    马上执行 END 动作; 如果已经在 END 动作内, 那就退出程序. 将 expression 作为程序的
    退出状态返回.
delete 语句

一个数组元素可以通过

delete array[subscript]

删除,例如, 下面这个循环删除数组 pop 中所有的元素

for (i in pop)
delete pop[i]

split 函数

函数 split(str,arr,fs) 将字符串 str 切割成一个个字段, 并存储到数组 arr 中. 字段的个数作为函数的返回值返回. 第 3 个参数 fs 的字符串值作为字段的分割符. 如果第 3 个参数被忽略, 就使用 FS。
函数

split(“7/4/76”, arr, “/”)

将字符串 7/4/76 分割成 3 个字段, 使用 / 作为分割符; 它将 7 存储在 arr[“1”], 将 4 存储在arr[“2”], 将 76 存储在 arr[“3”]。

多维数组

Awk 不直接支持多维数组, 但是它利用一维数组来
近似模拟多维数组. 虽然你可以写出像 i, j 或 s, p, q, r 这样的多维数组下标, 实际上 awk
会将它们都拼接起来 (下标之间用一个分隔符分开), 合成一个单独的下标. 举例来说,

awk '
for (i = 1; i <= 10; i++)
	for (j = 1; j <= 10; j++)
		arr[i, j] = 0
		'

创建了一个具有 100 个元素的数组, 下标具有形式 1,1, 1,2 等等. 在 awk 内部, 下标其实是以字符串的形式存储的。

自定义函数

除了内建函数, awk 还可以包含用户定义的函数. 定义函数的语句具有形式:

function name(patameter-list) {
	statements
}

一个函数定义可以出现在任何 模式–动作 语句可以出现的地方. 于是, awk 程序的通常形式就变成了一系列的, 由换行符或分号分开的 模式–动作 语句与函数定义。
在一个函数定义中, 函数体左花括号后的换行符, 与右花括号前的换行符都是可选的, 参数列表由一系列的由逗号分开的变量名构成; 在函数体内部, 这些变量引用的是函数被调用时传递给它的参数。函数体可能包含一个 return 语句, 用于将程序执行流返回至调用函数 (返回的时候可以带有一个值)。
举个栗子:

# 自定义函数
function max(m, n) {
	return m > n ? m : n
}

用户定义的函数可以在任何 模式–动作 语句的任何表达式中使用, 也可以在出现在任何函数体内。每一个对函数的使用都叫做一个 调用 (call)。举例来说, max 函数可以像这样调用:

{ print max($1, max($2, $3)) } # print maxinum of $1, $2, $3
	function max(m, n) {
		return m > n ? m : n
}

本节内容我们学习了 awk 的动作中支持的各种运算,包括表达式、常量、变量等,变量中包含了awk 的内建函数以及自定义函数,下节我们来学习awk 的输出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不务正业的攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值