小知识:awk 命令之流程控制
先前介绍了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语言的语法也让它没有失去代码的可阅读性。
作者:纯人工模式混淆
链接:https://juejin.cn/post/7023015880585904165