Chinaunix首页 | 论坛 | 博客
  • 博客访问: 503577
  • 博文数量: 119
  • 博客积分: 5054
  • 博客等级: 大校
  • 技术积分: 1305
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-03 13:13
文章分类

全部博文(119)

文章存档

2011年(4)

2010年(115)

我的朋友

分类:

2010-01-03 20:41:16

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中数组的特性
使用字符串当数组的下标(index).
使用数组前不须宣告数组名及其大小.
例如: 希望用数组来记录 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."]++ .

如何取出数组中储存的信息
以 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 

执行结果如下 :

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]++ }
END{for(course in Number) printf("%10s %d\n", course, Number[course] )}

第一个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]++ 之后
i=2时    $i="O.S."          Number["O.S."]         值从默认的0,变成了1 ;
i=3时    $i="Arch."         Number["Arch."]        值从默认的0,变成了1 ;
i=4时    $i="Discrete"      Number["Discrete"]     值从默认的0,变成了1 ;

第二个 Pattern { Actions }指令中END 为awk之保留字, 为 Pattern 的一种.
END 成立(其值为true)的条件是: "awk处理完所有数据, 即将离开程序时. "平常读入数据行时, END并不成立, 故其后的Actions 并不被执行;唯有当awk读完所有数据时, 该Actions才会被执行 ( 注意, 不管数据行有多少笔, END仅在最后才成立, 故该Actions仅被执行一次.)

BEGIN 与 END 有点类似, 是awk中另一个保留的Pattern.唯一不同的是: "以 BEGIN 为 Pattern 的 Actions 于程序一开始执行时, 被执行一次."

NF 为awk的内建变量, 用以表示awk正处理的数据行中, 所包含的字段个数.

awk程序中若含有以 $ 开头的自定变量, 都将以如下方式解释 :

以 i= 2 为例, $i = $2 表第二个字段数据. ( 实际上, $ 在 awk 中为一运算符(Operator), 用以取得字段数据.)

阅读(661) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~