小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
先前介绍了awk的变量的使用,但是有了变量却只能被动的使用,不能主动的控制,那多呆啊。
所以,awk它也为我们提供了用于控制程序逻辑的语法,比如循环语句,条件语句。
awk的for循环和c语言类似
for(i=xx;i<=xxxx;i++){
xxxx
}
主要区别就是变量申明的位置了,或者说awk本就没有所谓的申明,只是单纯为了初始化变量,所以就成了这个样子。我们最开始在写shell统计词频的时候,已经介绍了三种办法把一行多个字符串转为多行每行一个字符串了。而这里我们有了循环语句,自然可以用这个手动实现了。awk对于每一行的字符串会按照字段划分,并且它还有一个内建的变量NF表示当前行的字段数量。这样一来我们使用循环语句,把每行的每个字段都输出为一行也就完成了先前一样的效果。
代码如下:
awk '{
for(i=1;i<=NF;i++){
print $i
}
}'
有一点值得注意的是,awk中分割后的字段是从一开始的,而不是零。零号字段保存了整行的记录,1之后的才是分量。和c语言的左闭右开风格不一样。
awk的条件语句也是类似的,像下面这样
if (xxx ){
xxxxxx
}else if(xxx) {
xxxx
}else{
xxxx
}
我们可以先简单的试用一下这个条件语句,假设每三行我们要画一条分割线。可以借助awk自带的那个变量NR,先前我们用变量算平均数的使用。但当时我们只用了它在END时的值。实际上它与NF不一样,NR它应该看作当前已经处理过的行数,而NF则仅指当前行的字段数量。
用seq假装有18行的一个文件,代码可以这样写
seq 18 | awk '{print $0;if(NR%3==0){print "===================="}}'
从数据处理的角度看,有了条件分支,我们就可以实现关系代数中的一个重要的操作:选择。
举个例子,假设要选出所有成绩及格的人,姑且用seq代替文件,假设满分10分,6分及格。
可以像下面这样:
seq 10 | awk '{if($1>=6){print $0}}'
这样就筛选出了其中的满足条件的行。
如果把条件做一定的修改,我们实际上还能完成数据的填充(或者数据的修正),比如当数据为空时填充指定值(或者不正确的数据不输出或者改值)。
最后是小结,有了这些流程控制语句,awk 有了近似于脚本语言的表达能力,而近似C语言的语法也让它没有失去代码的可阅读性。