awk的流程控制,函数这一块,楼主以前没玩过,今天看了下,确实很有用。
看了一下awk的条件判断和循环和C语言的差不多,在这里就简单的mark下
条件判断
格式
if (expression)
{ action
.
.
}
else if (expression)
{ action
.
.
}
else
{
action
.
.
}
注意:上面的{}的位置随便放在啥地方都OK,当action只有一个的时候,可以不加{}
if和else放在同一行的时候,用分号隔开
if (expression) action1;else action2
如果条件表达式expression的值为真(非零或非空),就执行相应操作。条件表达式中可能包含算术运算符,关系操作符,或布尔操作符
条件操作符
条件操作符(?:)和C语言中的条件操作符一样。
格式:
expr?action1:action2
常用方式:
a=(x==y)1:2
循环
和C语言中一样,三种形式
while循环
while (condition){
action
.
}
do-while循环
do{
action
.
}while (condition)
注意:do循环至少执行一次循环体,然后再根据条件判断是否执行
for 循环
for (set_counter;test_counter;increment_counter)
{
action
.
}
set_counter:设置计数器的初值
test_counter:描述在循环开始时要测试的条件
increment_counter:每次在循环的底部递增计数器,且恰好在重新测试test_counter之前
注意:
1.循环和条件判断一样,当只有一个action的时候,{}可以不要。
2.注意一下循环中经常会用到i++和++i,这两个在单独使用的时候没啥区别。当和别的运算符结合使用的时候则有区别
如i=1;x=i++,表示先把i的值赋给x,然后i++,得到x的值为1,i的值为2。
而i=;x=++i,则是先i++,再把i++之后的值付给x,得到x的值为2,i的值为2
数组
1.awk的数组类似于C语言的数组形式,awk的关联数组类似于C语言中map容器,类似python的字典,以(key/value)的形式存储
2.相对于C语言的有一维数组,多维数组。awk较为简单了,只有一维数组。但是awk提供了一种方法来模拟多维数组,这是后话了
3.awk中我们不用声明数组,只需要为数组指定标识符,向数组中赋值就OK了
4.C语言可以如下,a[3]={1,2,3}初始化数组,awk不能这么做滴,只能类似这么做for (i=1;i<=3;i++) {a[i]=i}
OK,下面看看数组吧
数组形式
array[subscript] = value
看个例子,以NR为下标,$2为value加入数组。。然后在END例程中遍历打印数组
关联数组
其实在awk中所有的数组都是关联数组,和咱们传统脑子里的数组不同的是,关联数组的下标既可以是数字也可以是字符串。 其实在awk中存储的时候,不管是数字还是字符串都是以字符串的形式存储的
为什么叫关联数组呢,关联是谁和谁之间的关联?
关联其实就是咱们数组中的元素,下标和value存在一定的联系,咱们可以通过下标找到value。
相对于C语言中的数组,像a[1],a[2],a[3],这些值在内存中是顺序存储的,我们查找的时候也可以这么顺序的去查找。
而关联数组,的存储则是无序的,散列的,我们查找value值的时候,是通过下标和value之间的映射关系来查找的。
数组遍历
for (item in array)
print item,array[item]
成员测试
if (item in array)
print yes
举个小例子,看看数组的使用
测试文件
lixc boy liss girl
代码
awk ' BEGIN {FS = "\t";OFS = "\t" #设置输入输出字段分隔符 printf("Enter a glossary term:") } FILENAME == "glossary" { #匹配文件名glossary entry[$1] = $2 #$1为下标,$2为value,写入数组 next #该例程匹配到,则跳过下面的例程,读入下一行记录 } $0 ~ /^(quit|[qQ]|exit|[Xx])$/ {exit} #匹配退出条件 $0 != ""{ if ($0 in entry) #测试成员是否存在于数字中 { print entry[$0] } else print $0 "not found" } { printf("Enter another glossary term (q to quit):") } ' glossary - # "-" 是从终端输入
执行
用split()函数创建数组
和python中的split()有一点点类似,常用与从字段中提取子字段
用法
n = split(string,array,separator)
string:待分解到名字为array数组的输入字符串
array:数组名,数组的下标从1开始,一直到n
separator:指定的分隔符,可为字符,正则表达式,和字段的分解方式相同。如果不指定分隔符,则默 认使用FS的分割方法
n:返回的array数组的长度。
来个小例子,把01/05/2014或01-05-2014类型的时间改为01 05,2014类型
代码
awk ' BEGIN { listmonths = "January,February,March,April,May,June," listmonths = listmonths "July,August,September," #使用字符串连接的功能 listmonths = listmonths "October,November,December" split(listmonths,month,",") #生成数组 } $0 != ""{ #匹配输入不为空的行 sizeOfArray = split($1,date,"/") #以"/"为分隔符,分割数组 if (sizeOfArray == 1) #判读,是否分割成功 sizeOfArray = split($1,date,"-") #不成功,则以"-"分割 if (sizeOfArray == 1) #再判断 exit #不成功,说明输入不是"//"或"--"形式 date[1] += 0 print month[date[1]],date[2]","date[3] }'
执行结果
删除数组元素
delete array[subscript]
多维数组
awk不支持多维数组,只是用下标来模拟多维数组。
如:awk[3,2]=10 可以理解为第3行第2列,value为10。
但是下标3,2在存储的时候,其实还是一个下标。。3,2使用系统变量SUBSEP连接起来。
SUBSEP的默认值为\034。。那么3,2实际存储形式为3\342
成员测试
if ((i,j) in array)
系统变量数组
ENVIRON和ARGV
ENVIRON
环境变量数组,下标为环境变量的名字。
查看该数组的详细内容
awk 'BEGIN{for (env in ENVIRON) print env"------"ENVIRON[env]}'
ARGV
命令行参数数组,不包括脚本本身和其他任何awk的指定选项。参数个数可以用ARGC获得,数组的第一个下标为0,最后一个下标为ARGC-1
这东西在BEGIN例程中用的挺好的
在主循环例程中,就有点小问题了