0
点赞
收藏
分享

微信扫一扫

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

老牛走世界 2022-02-16 阅读 74

目录

动作

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

表达式

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

常量

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 的值之前为 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 语句用于循环。

delete 语句

一个数组元素可以通过

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

split 函数

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

将字符串 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 条评论