【译】 AWK教程指南 5AWK中的数组
awk程序中允许使用字符串当做数组的下标(index)。利用这个特色十分有助于资料统计工作。(使用字符串当下标的数组称为Associative Array)
首先建立一个数据文件,并取名为 reg.dat。此为一学生注册的资料文件;第一栏为学生姓名,其后为该生所修课程。
awk中数组的特性
1. 使用字符串当数组的下标(index)。
2. 使用数组前不须声明数组名及其大小。
例如:希望用数组来记录 reg.dat 中各门课程的修课人数。这情况,有两项信息必须储存:
(a) 课程名称,如: "O.S.","Arch.".. ,共有哪些课程事先并不明确。
(b) 各课程的修课人数。 如:有几个人修"O.S."
在awk中只要用一个数组就可同时记录上列信息。其方法如下:
使用一个数组 Number[ ]:
* 以课程名称当 Number[ ] 的下标。
* 以 Number[ ] 中不同下标所对映的元素代表修课人数。
例如:
有2个学生修 "O.S.",则以 Number["O.S."] = 2 表示。
若修"O.S."的人数增加一人,则 Number["O.S."] = Number["O.S."] + 1
或 Number["O.S."]++ 。
3. 如何取出数组中储存的信息
以 C 语言为例,声明 int Arr[100];之后,若想得知 Arr[ ]中所储存的数据,只须用一个循环,如:
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将会找到 "O.S.","Arch.",...
使用该指令时,须指定所要查找的数组,及一个变量。awk会使用该变量来记录从数组中找到的每一个下标。例如
for(course in Number){
...
}
指定用 course 来记录 awk 从Number[ ] 中所找到的下标。awk每找到一个下标时,就用course记录该下标的值且执行{....}中的指令。通过这个方式便可取出数组中储存的信息。(详见下例)
范例:统计各科修课人数,并印出结果。
建立如下程序,并取名为 course.awk:
{ for( i=2; i <= NF; i++) Number[$i]++ }
END{
for(course in Number)
printf("%10s %d\n", course, Number[course] )
}
执行下列命令:
$ awk -f course.awk reg.dat
执行结果如下:
说 明:
1. 这程序包含两个Pattern { Actions }指令。
Pattern | Actions |
{ for( i=2; i <= NF; i++) Number[$i]++ } | |
END | { for(course in Number) printf("%10s %d\n", course, Number[course]) } |
2. 第一个Pattern { Actions }指令中省略了Pattern 部分。故随着每行数据的读入其Actions部分将逐次无条件被执行。以awk读入第一条记录 " Mary O.S. Arch. Discrete" 为例,因为该笔数据 NF = 4(有4个字段),故该 Action 的for Loop中i = 2,3,4。
i | $i | 最初 Number[$i] | Number[$i]++ 之后 |
2 | "O.S." | AWK default Number["O.S."] = 0 | 1 |
3 | "Arch." | AWK default Number["Arch."] = 0 | 1 |
4 | "Discrete" | AWK default Number["Discrete"] = 0 | 1 |
3. 第二个 Pattern { Actions }指令中
* END 为awk的保留字,为 Pattern 的一种。
* END 成立(其值为true)的条件是:"awk处理完所有数据,即将离开程序时。"
平常读入数据行时,END并不成立,故其后的Actions 并不被执行;唯有当awk读完所有数据时,该Actions才会被执行(注意,不管有多少行数据,END仅在最后才成立,故该Actions仅被执行一次。)
BEGIN 与 END 有点类似,是awk中另一个保留的Pattern。唯一不同的是:
"以 BEGIN 为 Pattern 的 Actions 于程序一开始执行时,被执行一次。"
4. NF 为awk的内置变量,用以表示awk正处理的数据行中,所包含的字段个数。
5. awk程序中若含有以 $ 开头的自定变量,都将以如下方式解释:
以 i= 2 为例,$i = $2 表第二个字段数据。 (实际上,$ 在 awk 中为一运算符(Operator),用以取得字段数据。)