本部分内容参考自《Linux命令行与shell脚本编程大全 第3版》。
gawk 编程语言提供了不少内置函数,可进行一些常见的数学、字符串以及时间函数运算。你可以在 gawk 程序中利用这些函数来减少脚本中的编码工作。
数学函数
如果你有过其他语言的编程经验,可能就会很熟悉在代码中使用内建函数来进行一些常见的数学运算。 gawk 编程语言不会让那些寻求高级数学功能的程序员失望。
下表列出了 gawk 中内建的数学函数:
函数 | 描述 |
---|---|
atan2(x, y) | x/y 的反正切,x 和 y 以弧度为单位 |
cos(x) | x 的余弦,x 以弧度为单位 |
exp(x) | x 的指数函数 |
int(x) | x 的整数部分,取靠近零一侧的值 |
log(x) | x 的自然对数 |
rand() | 比 0 大比 1 小的随机浮点值 |
sin(x) | x 的正弦,x 以弧度为单位 |
sqrt(x) | x 的平方根 |
srand(x) | 为计算随机数指定一个种子值 |
虽然数学函数的数量并不多,但 gawk 提供了标准数学运算中要用到的一些基本元素。 int()
函数会生成一个值的整数部分,但它并不会四舍五入取近似值。它的做法更像其他编程语言中的 floor
函数。它会生成该值和 0 之间最接近该值的整数。
这意味着 int()
函数在值为 5.6
时返回 5
,在值为 -5.6
时则返回 -5
。
rand()
函数非常适合创建随机数,但你需要用点技巧才能得到有意义的值。rand()
函数会返回一个随机数,但这个随机数只在 0
和 1
之间(不包括 0
或 1
)。要得到更大的数,就需要放大返回值。
产生较大整数随机数的常见方法是用 rand()
函数和 int()
函数创建一个算法。
x = int(10 * rand())
这会返回一个 0~9
(包括 0
和 9
)的随机整数值。只要为你的程序用上限值替换掉等式中的 10
就可以了。
除了标准数学函数外, gawk 还支持一些按位操作数据的函数。
and(v1, v2)
:执行值v1
和v2
的按位与运算;compl(val)
:执行val
的补运算;lshift(val, count)
:将值val
左移count
位;or(v1, v2)
:执行值v1
和v2
的按位或运算;rshift(val, count)
:将值val
右移count
位;xor(v1, v2)
:执行值v1
和v2
的按位异或运算;
位操作函数在处理数据中的二进制值时非常有用。
字符串函数
gawk 编程语言还提供了一些可用来处理字符串值的函数,如下表:
函数 | 描述 |
---|---|
asort(s [,d]) | 将数组 s 按数据元素值排序。索引值会被替换成表示新的排序顺序的连续数字。另外,如果指定了 d ,则排序后的数组会存储在数组 d 中 |
asorti(s [,d]) | 将数组 s 按索引值排序。生成的数组会将索引值作为数据元素值,用连续数字索引来表明排序顺序。另外如果指定了 d ,排序后的数组会存储在数组 d 中 |
gensub(r, s, h [, t]) | 查找变量 $0 或目标字符串 t (如果提供了的话)来匹配正则表达式 r 。如果 h 是一个以 g 或 G 开头的字符串,就用 s 替换掉匹配的文本。如果 h 是一个数字,它表示要替换掉第 h 处 r 匹配的地方 |
gsub(r, s [,t]) | 查找变量 $0 或目标字符串 t (如果提供了的话)来匹配正则表达式 r 。如果找到了,就全部替换成字符串 s |
index(s, t) | 返回字符串 t 在字符串 s 中的索引值,如果没找到的话返回 0 |
length([s]) | 返回字符串s的长度;如果没有指定的话,返回 $0 的长度 |
match(s, r [,a]) | 返回字符串 s 中正则表达式 r 出现位置的索引。如果指定了数组 a ,它会存储 s 中匹配正则表达式的那部分 |
split(s, a [,r]) | 将 s 用 FS 字符或正则表达式 r (如果指定了的话)分开放到数组 a 中。返回字段的总数 |
sprintf(format, variables) | 用提供的 format 和 variables 返回一个类似于 printf 输出的字符串 |
sub(r, s [,t]) | 在变量 $0 或目标字符串 t 中查找正则表达式 r 的匹配。如果找到了,就用字符串 s 替换掉第一处匹配 |
substr(s, i [,n]) | 返回 s 中从索引值i开始的 n 个字符组成的子字符串。如果未提供 n ,则返回 s 剩下的部分 |
tolower(s) | 将 s 中的所有字符转换成小写 |
toupper(s) | 将 s 中的所有字符转换成大写 |
一些字符串函数的作用相对来说显而易见。
$ gawk 'BEGIN{x = "testing"; print toupper(x); print length(x) }'
TESTING
7
但一些字符串函数的用法相当复杂。asort
和 asorti
函数是新加入的 gawk 函数,允许你基于数据元素值(asort
)或索引值(asorti
)对数组变量进行排序。这里有个使用 asort
的例子。
$ gawk 'BEGIN{
arr1["a"]=22;
arr1["b"]=4;
arr1["c"]=8;
asort(arr1,arr2);
for(i in arr2){
print "index: ",i," value: ",arr2[i];
}
}'
index: 1 value: 4
index: 2 value: 8
index: 3 value: 22
新数组 arr
含有排序后的原数组的数据元素,但索引值现在变为表明正确顺序的数字值了。
split
函数是将数据字段放到数组中以供进一步处理的好办法。
$ gawk -F, '{
> split($0,arr);
> print arr[1],arr[5];
> }' test3.txt
data11 data15
data21 data25
data31 data35
新数组使用连续数字作为数组索引,从含有第一个数据字段的索引值 1
开始。
时间函数
gawk 编程语言包含一些函数来帮助处理时间值,如下表所示:
函数 | 描述 |
---|---|
mktime(datespec) | 将一个按 YYYY MM DD HH MM SS [DST] 格式指定的日期转换成时间戳值 |
strftime(format [,timestamp]) | 将当前时间的时间戳或 timestamp (如果提供了的话)转化格式化日期(采用 shell 函数date() 的格式) |
systime() | 返回当前时间的时间戳 |
时间函数常用来处理日志文件,而日志文件则常含有需要进行比较的日期。通过将日期的文本表示形式转换成 epoch 时间(自 1970-01-01 00:00:00 UTC
到现在的秒数),可以轻松地比较日期。
下面是在 gawk 程序中使用时间函数的例子。
$ gawk 'BEGIN{
timeNum = systime()
currTime = strftime("%Y-%m-%d %H:%M:%S",timeNum)
print currTime
}'
2019-12-25 14:44:11
该例用 systime
函数从系统获取当前的 epoch
时间戳,然后用 strftime
函数将它转换成用户可读的格式,转换过程中使用了 shell 命令 date
的日期格式化字符。
这里时间戳是指自
1970-01-01 00:00:00 UTC
到现在,以秒为单位的计数,通常称为 epoch time。systime()
函数的返回值也是这种形式。
评论区