一个简单的 Awk Language 程序

Awk的推荐书籍:《The AWK Programming Language》Aho&Weinberger&Kernighan


1 AWK

电脑用户有时会花大量时间来做一些简单的、需手工操作数据的操作--- 修改数据的格式,核对数据的正确性,根据某些属性查找某项目,求和,打印报告等操作。所有这些操作都应该机械化,但是要用C或者Pascal这样的语言来每次为这样一些操作来专门编写一个程序又显得有些心有余而力不足。


AWK是这样的一个编程语言,用它编程来实现以上目标时AWK代码会非常短,经常只需要一两行就可以搞定这些工作。AWK程序是一系列“模式-动作”的代码,AWK将输入文件的每一行来和程序中的模式匹配,只要输入行匹配“模式”后就执行此“模式”对应的“动作”。“模式”可以用“正则表达式”及比较运算符运用在“字符串”、“数字”、“字段”、“变量”、“数组元素”的表达式来表达。“动作”的代码类似C语言,但不需要任何的声明,字符串和数字是内建的数据类型。


AWK程序将程序中的变量自动初始化为0,AWK自动浏览输入文件并将每一行分成多个字段。因为AWK拥有太多自动的特性---- “文件输入,字段分裂,存储管理,初始化”让Awk程序比通常的计算机语言程序要简短许多。


Awk语言的简洁性和方便的操作使得其能应用在编写大型程序的模型(模子)之上。Awk程序的开始只需要那么几行,然后就是用来处理文件的程序。由于Awk的简短性使Awk容易上手,然后能够用Awk语言构造另外一种语言(如果设计对了的话)。


2 一个简单的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"
}

在linux的终端下运行该awk程序,lly7@debian:~/AWK$  awk  -f  TestAlgo.awk  awk.dat

运行结果如下:

AWK Application Start
LXR
AWK Application END


这是一个具有awk完整结构的awk程序。BEGIN和END是awk内建的模式,程序运行开始运行BEGIN模式后的语句,程序运行完毕运行END模式后的语句。$1表示awk.dat文件中当前行的第一个字段,$2是awk.dat文件当前行的第二个字段,它表示第一个字段为“L”时就输出第二个字段到stdin之上。


3 AWK内建变量

内建变量在程序中有特定的含义,这类变量在使用前被系统自动赋了相应的值。


Figure1:Awk内建变量


4 Awk 关联数组

和数组不同的是, 关联数组的索引值不是非负的整数而是任意的标量。这些标量称为Keys,可以在以后用于检索数组中的数值。

摘《Programming Pearls,编程珠玑》里的例子:给定包含n个名字的文件(每个名字占一行),生成全部n^2个名字对。可用Awk简短的程序来实现:

{ name[++n] = $1 }
END { for( i = 1; i <= n; i++ )
        for(j = 1; j <= n; j++)
              print name[i], name[j]
    }

解析

(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
    }
解析:数组以文件中的第一个字段来座位数组的“下标索引”,即使在文件中有相同的$1,但在$1作为数组索引时就不会在name中有相同的名字。


5 Awk程序结构

Awk程序的结构如下:

BEGIN { preprocessing }
pattern { action for each input line}
END { postprocessing}
在Awk程序中,这三个部分中任何一个部分都可以缺省。


1. 模块

BEGIN:     BEGIN是一种特殊的模式,它与Awk程序读取文件第一行之前的状态相匹配,然后执行“preprocessing”部分。

pattern:        pattern是Awk程序在读文件当前行的模式。要匹配pattern后,在当前行的位置上“action for each input line”部分才会被执行。

END:      END是一种特殊的模式,它与Awk程序读完文件最后一行后的状态匹配,然后执行“postprocessing”部分。


2. 模式(pattern)

Awk的模式灵活,总结如下图:



Figure2:Awk pattern总结

字符串匹配模式


正则表达式模式


3. 动作

可在动作部分书写的程序语句如下总结:



4. Awk函数

Awk拥有许多种类的内建函数,如字符创处理函数、算术运算函数等,使用时可查看Awk手册。


Awk除了内建函数之外也允许用户自定义函数,自定义函数时需要遵循的规则如下:

function name( parameter-list ) {
    statements
}
函数的定义就跟“模式-动作”语句一样,随处都可以定义。如此的Awk程序就是由Awk语句和Awk函数组成的了,语句和函数之间通过换行或者分号隔开。


如function       max(m, n) {

                return  m > n ? m :n

}

语句末尾不需有分号。


6 初识Awk总结

都说“人生若只如初见”很美好,初见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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值