awk的使用 第4部分 在awk中使用数组

 awk程序中允许使用字符串当做数组的下标(index),这个特点有助于资料的统计。(使用字符串当下标的数组称为Associative  Array)
    首先建立一个名为kecheng.dat数据文件,内容是学生选课的内容;第一栏为学生姓名,其后为该生所学课程,内容如下:
 [root@benet pub]# cat kecheng.dat
zhangsan math english chinese
lisi     computer chinese english
wangwu dianzi chinese math
zhaoliu huanjing english chinese
    awk中数组不需要声明,也不用指定数组的大小,直接使用字符串当数组的下标(index)。 以上边学生选课为数据文件统计一下kecheng.dat 中学习各门课程的人数。
    这种情况,有二项信息必须储存: (a) 课程名称, 如:math,English,共有哪些课程事先并不明确。 (b)各课程的选修人数。 如: 有几个人选修了“math”。


      在awk 中只用一个数组就可同时记录上述信息。 方法如下:使用数组Number[ ]:以课程名称当Number[ ]的下标。 以Number[ ] 中不同下标所对映的元素代表各门课程的人数。 例如:有2个学生学习“math”,则以Number["math"]=2表示。如果学习math的人数增加一人,则Number[“math”]=Number[“math”]+1 或Number[“math”]++ 将学习该门课程的人数加1。
    那么如何读出数组中储存的信息呢?以math为例,声明int Arr[100]数组后,如果想显示数组中的数值,使用一个for循环就可以了,如:for(i=0; i<100; i++) printf(“%d/n”, Arr[i]); 即可。上式中:数组Arr[ ] 的下标 :0,1,2,…,99, 数组Arr[ ] 中各下标所对应的值:Arr[0],Arr[1],…,Arr[99]。
    上面说了awk 中使用数组不须声明,以数组number[]为例,程序执行前,并不知有哪些课程名称可能被当成Number[ ]的下标。在awk中提供了一个指令,通过该指令awk会自动找寻数组中所有使用过的下标。以Number[ ] 为例,awk将会找到“math”,“english”,使用该指令时,只要首先指定要找寻的数组和变量即可,awk会记录从数组中找到的每一个下标。
    例如:for(course in Number){…}
     指定使用course 来记录awk 从Number[ ]中找到的下标,awk每找到一个下标,就用course记录该下标的值且执行{…}中的指令。
   例子:统计kecheng.dat中每门课程有多少学生学习,并输出结果。
 处理方法:建立使用awk编写的脚本程序,脚本的内容如下:
[root@benet pub]# cat course.awk
#!/bin/awk -f
BEGIN{
FS=” “}
{
for(i=2;i<=NF;i++){number[$i]++;}
}
END{
for(course in number)printf(“%10s %d/n”,course,number[course]);
}
    在程序中需要注意,awk程序主要有三部分组成,BEGIN,中央处理部分和END三个部分,BEGIN和END是awk的保留字,后面必须是“{”,如果没有紧跟着“{”,执行程序的时候,会报错;FS是field separate的缩写,用来存储域分隔符。
    执行结果如下:
[root@benet pub]# awk -f course.awk kecheng.dat
  computer 1
   english 3
    dianzi 1
   chinese 4
      math 2
  huanjing 1
    程序解释:这程序包含三个Pattern { Actions }指令。
    第一个Pattern { Actions }指令中的FS上面已经说过了,后面跟着分隔数据文件的分隔符,在这里,是以空格来进行分隔数据行的没一个部分的,所以FS=” “;如果是分隔/etc/passwd这个文件,那么FS=”:”,在以后分隔数据文件的时候,一定要选择正确的域分隔符,并用FS进行设置。
    第二个Pattern { Actions }指令中省略了Pattern 部分,所以每行数据读入后,都会在Actions部分将逐次无条件执行。awk在读入第一行数据zhangsan math english chinese的时候,因为该行数据有NF=4个字段,所以Action 的for循环中i从2开始,因为第一个字段是学生的名字,不用进行统计;而其后的各个域需要统计,所以for循环中i取值为2,3,4。Number[$i]++ 这句中,在i=2时,$2是第二个域的值,即$2=math,Number[math]的值从默认的0,++变成了1 ; i=3时$i=english,Number[english]的值默认是0,++变成了1 ; 同理,i=4时 $i=chinese,Number[chinese]的值从默认的0,++后变成了1 ;   第一行数据处理完后,再次读入下一行,根据$i的内容,如果数组中没有,就会新添加一个课程,并将选择给课程的学生数加1,如果该课程在数组中已经存在,只将改课程的人数加1。
    第三个Pattern{Actions}指令中END 为awk的保留字,而且必须是大写,是Pattern的一种。END 成立(其值为true)的条件是: “awk处理完所有数据,即将离开程序时”,平常读入数据行时,END并不成立,所以END后面的Actions 并不被执行;只有当awk读完所有数据时,Actions才会被执行。

     BEGIN与END 有点类似,是awk 中另一个保留的Pattern。 唯一不同的是:“以BEGIN 为Pattern的Actions 在程序一开始的时候被执行一次”, NF 为awk 的内建变量,用来表示awk正在处理的数据行中所包含的字段的个数。  

     awk程序中以$开头的变量, 都是下面这种意思:以i= 2 为例,$i=$2 表示第二个字段数据(实际上,$在awk 中 为一运算符(Operator),用以取得字段数据)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值