cmd_list2}
else if {cmd_list3}
else {cmd_list}
}
还支持多目操作符。
expression ? action1 : action2
其中"?"和":"还可以继续嵌套。
6.2 while循环
结构:
PATTERN {
cmd1
while (test_cmd)
cmd
}
当cmd有多个时,使用大括号包围。
PATTERN {
cmd1
while (test_cmd){
cmd2
cmd3
....
}
}
一行书写格式:
PATTERN{cmd1;while (test_cmd){cmd1;cmd2}}
6.3 do循环
和while循环类似,地位和shell中的until循环一样。都是至少执行一次命令列表。
结构:
PATTERN {
do{
cmd1
cmd2
} while (test_cmd)
}
6.4 for循环
结构大致如下:
PATTERN {
for (i=1;i<=10;++i){
cmd1
cmd2
}
}
for后括号中包括:变量初始值,条件判断和计数器增长表达式。
7.更完整的awk程序格式和表达式
更完整的awk程序的语法格式有以下几种:
BEGIN{actions} END{actions} expr{actions} /regexp/{actions}:可被regexp匹配的行才执行actions expr1,expr2{actions}:表示范围,从满足expr1的行开始,到满足expr2的行结束
其中:
expr
是表达式。
- 比较操作符有:
< <= == != >= > ~ !~
。
- 算术操作符有:
+ - * / % ^(取幂) **(取幂)
。其中**
非POSIX标准,不可移植。
- 赋值操作符有:
++ -- += -= *= /= %= ^= **=
。awk支持复合赋值,例如FS = OFS = "\t"
表示字段分隔符和输出字段分隔符都被赋值为制表符。
/regexp/
为正则匹配模式,表示该行能被regexp匹配则为真。还有以下两种匹配表达式,分别表示给定的字符串能(不能)匹配就为真。
- string ~ /regexp/
- string !~ /regexp/
- 还有符合模式的表达式。使用逻辑操作符"&&"、"||"和"!"连接。如
$4 == "Asia" && $3 > 500
,! (NR > 1 && NF > 3)
。
awk中字符串和数值数据类型是自动转换的。如果想要得到一个字符串值,可以value ""
进行转换,同理,如果想要得到一个数值,可以value + 0
。
另外,正则表达式可以不用包围在两个斜杠中。可以将正则表达式赋值给一个变量,然后使用该变量取匹配数据。例如:
reg="^[0-9]+$"
$2 ~ reg
甚至直接使用双引号替换斜杠也允许。但不建议使用,因为一个元字符可能需要多个反斜杠来保护,使得看上去极其晦涩。
8.awk中的变量
普通变量:给变量赋值时,如果要赋值字符串,则该字符串应该使用双引号包围,特别是包含特殊字符时。赋值数值时无所谓。 字段变量:$1,$2,$3,...,$NF,还有"$0"表示整行内容。另外,可以直接赋值一个新字段或修改字段值。但这都会影响"$0"。同理,修改"$0"也会影响各字段值。
内置变量:其实可以分为两类,一类是awk内部自动修改的变量,如行数变量NR,一类是内部不会改动的系统变量,如输入字段分隔符变量FS,完全需要手动修改,这类一般都有默认值。
- ARGV:命令行参数数组。从0开始计数知道ARGC-1。
- ARGC:ARGV数组元素的个数。
- FILENAME:当前处理的文件名。
- FNR:当前处理文件的记录号。(file record num)
- NR:已处理的总记录数。多个文件时不重置。(record num)
- NF:当前记录的字段总数。(field num)
- FS:输入的字段分隔符。默认为空白。(file separate)
- OFS:输出的字段分隔符。默认为空白。(output record separate)
- RS:输入流的记录分隔符。默认为"\n"。该变量只取值第一个字符。(record separate)
- ORS:输出流的记录分隔符。默认为"\n"。该变量只取值的第一个字符。(output record separate)
- OFMT:printf输出数值转换成字符串输出时的格式。默认为"%.6g"。
- CONVFMT:printf输出数值转换成字符串输出时的格式。会被OFMT覆盖。默认为"%.6g"。
- RLENGTH:被match函数匹配的字符串的长度。
- RSTART:被match函数匹配的字符串的开始位置。
- SUBSEP:下标分隔符。默认为"\034",ASCII中034代表的是双引号'"'。
注意,像NR、FNR、RS等的对象是记录(record),而非行。只有当RS="\n"时,读取了一行才表示读取了一条记录。
9.awk中的内置函数
awk有两类内置函数:算术函数和字符串函数。还支持自定义函数。
算术函数:
- cos(x):取x的余弦。
- sin(x):取x的正弦。
- sqrt(x):取x的平方根。
- rand():返回一个随机数r,其中
0<=r<1
。
- srand(x):设置rand()的种子值为x。种子值相同时,rand()的结果相同。可
print srand()
输出当前种子值。
- int(x):取x的整数部分。
因此,要生成一个范围[1,n]的随机数,使用int(n*rand() + 1)
,要四舍五入一个数值,使用int(x + 0.5)
。
随机数的种子值相同时,rand的结果总是相同。如下两次运行结果,两次结果中,前两个rand()值相同,后两个rand()值不同,因为中间使用了srand()重设种子值。
awk 'BEGIN{print rand();print rand();srand();print rand();print rand();print srand()}'
0.237788
0.291066
0.109925
0.983692
1504560578
awk 'BEGIN{print rand();print rand();srand();print rand();print rand();print srand()}'
0.237788
0.291066
0.96322
0.670495
1504560604
字符串函数:建议下面的所有regexp都使用"//"包围。
index(str1,str2)
:返回子串str2在字符串str1中第一次出现的位置。如果没有指定str1,则返回0。
length(str1)
:返回字符串str1的长度。如果未给定str1,则表示计算"$