Awk的推荐书籍:《The AWK Programming Language》Aho&Weinberger&Kernighan
电脑用户有时会花大量时间来做一些简单的、需手工操作数据的操作--- 修改数据的格式,核对数据的正确性,根据某些属性查找某项目,求和,打印报告等操作。所有这些操作都应该机械化,但是要用C或者Pascal这样的语言来每次为这样一些操作来专门编写一个程序又显得有些心有余而力不足。
AWK是这样的一个编程语言,用它编程来实现以上目标时AWK代码会非常短,经常只需要一两行就可以搞定这些工作。AWK程序是一系列“模式-动作”的代码,AWK将输入文件的每一行来和程序中的模式匹配,只要输入行匹配“模式”后就执行此“模式”对应的“动作”。“模式”可以用“正则表达式”及比较运算符运用在“字符串”、“数字”、“字段”、“变量”、“数组元素”的表达式来表达。“动作”的代码类似C语言,但不需要任何的声明,字符串和数字是内建的数据类型。
AWK程序将程序中的变量自动初始化为0,AWK自动浏览输入文件并将每一行分成多个字段。因为AWK拥有太多自动的特性---- “文件输入,字段分裂,存储管理,初始化”让Awk程序比通常的计算机语言程序要简短许多。
Awk语言的简洁性和方便的操作使得其能应用在编写大型程序的模型(模子)之上。Awk程序的开始只需要那么几行,然后就是用来处理文件的程序。由于Awk的简短性使Awk容易上手,然后能够用Awk语言构造另外一种语言(如果设计对了的话)。
既然AWK程序是为文件而生的,首先在linux下创建一个awk程序的文件awk.dat,里面的内容为“L LXR”。然后创建awk程序文件 vi TestAlgo.awk,编写程序
BEGIN{ print "AWK Application Start" } $1=="L" {print $2} END{ print "AWK Application END" }
运行结果如下:
AWK Application Start
LXR
AWK Application END
这是一个具有awk完整结构的awk程序。BEGIN和END是awk内建的模式,程序运行开始运行BEGIN模式后的语句,程序运行完毕运行END模式后的语句。$1表示awk.dat文件中当前行的第一个字段,$2是awk.dat文件当前行的第二个字段,它表示第一个字段为“L”时就输出第二个字段到stdin之上。
Figure1:Awk内建变量
和数组不同的是, 关联数组的索引值不是非负的整数而是任意的标量。这些标量称为Keys,可以在以后用于检索数组中的数值。
摘《Programming Pearls,编程珠玑》里的例子:给定包含n个名字的文件(每个名字占一行),生成全部n^2个名字对。可用Awk简短的程序来实现:
{ name[++n] = $1 } |
解析:
(1) 此段Awk程序省略了BEGIN预处理部分,只有处理文件和后续输出部分。
(2) 数组name不用声明直接引用,n被初始化为0。程序开始执行后自动以循环的方式读取文件的每一行,将每一行的第一个字段内容($1)赋值给数组的当前元素。
(3)读取文件完毕后输出名字对,生成n^2名字对。
如果输入文件中的名字有重复的就不必再组队了,故而需要避免两个相同名字成对。此时可用以下码来避免这种情况的发生:
{ name[$1] = 1} END { for (i in name) for(j in name) print i, j } |
BEGIN { preprocessing } pattern { action for each input line} END { postprocessing} |
BEGIN: BEGIN是一种特殊的模式,它与Awk程序读取文件第一行之前的状态相匹配,然后执行“preprocessing”部分。
pattern: pattern是Awk程序在读文件当前行的模式。要匹配pattern后,在当前行的位置上“action for each input line”部分才会被执行。
END: END是一种特殊的模式,它与Awk程序读完文件最后一行后的状态匹配,然后执行“postprocessing”部分。
字符串匹配模式:
正则表达式模式:
Awk拥有许多种类的内建函数,如字符创处理函数、算术运算函数等,使用时可查看Awk手册。
function name( parameter-list ) { statements } |
如function max(m, n) {
return m > n ? m :n
}
语句末尾不需有分号。
都说“人生若只如初见”很美好,初见Awk时也是一样,但如果后续还要遇到Awk则会一样的认为Awk并不像初识那么简单,它依然会有复杂的一面(如那一堆堆正则表达式),但如果用时间为代价将Awk用熟练了的话就会比初识Awk更美好。同理,人生也一样,相识就识透称为知己,如果有可能的话。
Awk用模式测试每一个输入行,当模式匹配时就执行与此模式对应的动作。模式可以包含数字或字符串的比较,动作可以包含运算和格式化输出。另外Awk自动读取文件的每行的进一步将每一个输入行分裂成字段,它还包含了许多的内建变量同时也可以在程序中无需声明的使用自定义的变量。应用这些特性,一些运算程序就可以用很短的Awk程序实现了。
总结一下,Awk程序的规模减小归功于Awk的几个特性:
(1) 输入行之上的隐式循环。
(2) 自动将输入行分隔成字段。
(3) 变量的初始化和转换。
(4) 关联数组。
初识Awk后,基本能够读懂简单的Awk程序了,更复杂一点的Awk借助于手册之后也应该能看懂。有时候就是需要看懂Awk小程序以体会其中包含的算法(Awk因其编码的简短性和关联数组,适合描述算法)。当然Awk的实际应用之处也是有的:比如在linux之上编写Shell脚本的时候或者直接编写Awk程序就可以管理甚多东西了,比编写C语言程序都要简单。
AWK Note Over。