原文:http://doc.lazyhack.net/awk.htm
awk程序中允许使用字符串当做数组的下标(index). 利用这个特色十分有助于资料统计工作.(使用字符串当下标的数组称为Associative Array)
首先建立一个数据文件, 并取名为 reg.dat. 此为一学生注册的资料文件; 第一栏为学生姓名, 其后为该生所修课程.
Mary O.S. Arch. Discrete
Steve D.S. Algorithm Arch.
Wang Discrete Graphics O.S.
Lisa Graphics A.I.
Lily Discrete Algorithm
awk中数组的特性
1、使用字符串当数组的下标(index).
2、使用数组前不须声明数组名及其大小.
例如: 希望用数组来记录 reg.dat 中各门课程的修课人数.
这情况,有二项信息必须储存:
(a) 课程名称, 如: "O.S.","Arch.".. ,共有哪些课程事先并不明确.
(b)各课程的修课人数. 如: 有几个人修"O.S."
在awk中只要用一个数组就可同时记录上列信息. 其方法如下:
使用一个数组 Number[ ] :
以课程名称当 Number[ ] 的下标.
以 Number[ ] 中不同下标所对映的元素代表修课人数.
例如:有2个学生修 "O.S.", 则以 Number["O.S."] = 2 表之.
如何取出数组中储存的信息
awk 提供了一个指令, 由该指令awk会自动找寻数组中使用过的所有下标. 以 Number[ ] 为例, awk将会找到 "O.S.", "Arch.",...
使用该指令时, 须指定所要找寻的数组, 及一个变量. awk会使用该的变量来记录从数组中找到的每一个下标. 例如
for(course in Number){....}
指定用 course 来记录 awk 从Number[ ] 中所找到的下标. awk每找到一个下标时, 就用course记录该下标之值且执行{....}中之指令. 藉由这个方式便可取出数组中储存的信息.
例子:
统计各科修课人数,并印出结果.
awk '{for (i=2;i<=NF;i++)a[$i]+=1}END{for (i in a)printf ("%10s %d\n",i,a[i])}' reg.dat
输出结果
Graphics 2
O.S. 2
Discrete 3
A.I. 1
D.S. 1
Arch. 2
Algorithm 2
说明:程序包含两个pattern{actions}
{ for( i=2; i <= NF; i++) Number[$i]++ }:省略了pattern故无条件的对所有行执行后面actions
awk读入第一行 " Mary O.S. Arch. Discrete"为例,NF=4,所以for loop中的i=2,3,4
i=2时,$i=$2= "O.S." Number[$i]=Number[$2]= Number["O.S."] 由默认值0变成1
i=3时,$i=$3= "Arch." Number[$i]=Number[$3]=Number["Arch."] 由默认值0变成1
i=4同理
END{for(course in Number) printf("%10s %d\n", course, Number[course] )}
该指令中END是awk的保留字,为pattern的一种其成立(值为true)的条件是:“awk处理完所有的数据,即将离开程序时。”
当读入行的时候END不成立,故不执行后面的actions,当awk读完所有的数据时,改actions会被执行,且只被执行一次。
BEGIN和END类似,相反以BEGIN为pattern的actions只会在awk读取数据前执行一次
注意:以 i= 2 为例, $i = $2 表第二个字段数据. ( 实际上, $ 在 awk 中为一运算符(Operator), 用以取得字段数据.)