全部博文(584)
分类: LINUX
2010-01-06 15:27:34
awk 是一种程序语言. 它具有一般程序语言常见的功能.
因 awk语言具有某些特点, 如 : 使用直译器(Interpreter)不需先行编译; 变量无类型之分(Typeless), 可使用文字当数组的下标(Associative Array)…等特色. 因此, 使用awk撰写程序比起使用其它语言更简洁便利且节省时间. awk还具有一些内建功能, 使得awk擅于处理具数据行(Record), 字段(Field)型态的资料; 此外, awk内建有pipe的功能, 可将处理中的数据传送给外部的 Shell命令加以处理, 再将Shell命令处理后的数据传回awk程序, 这个特点也使得awk程序很容易使用系统资源.
由
于awk具有上述特色, 在问题处理的过程中, 可轻易使用awk来撰写一些小工具;
这些小工具并非用来解决整个大问题,它们只扮演解决个别问题过程的某些角色,
可藉由Shell所提供的pipe将数据按需要传送给不同的小工具进行处理, 以解决整个大问题. 这种解题方式,
使得这些小工具可因不同需求而被重复组合及重用(reuse); 也可藉此方式来先行测试大程序原型的可行性与正确性,
将来若需要较高的执行速度时再用C语言来改写.这是awk最常被应用之处. 若能常常如此处理问题, 读者可以以更高的角度来思考抽象的问题,
而不会被拘泥于细节的部份.
为便于解释awk程序架构, 及有关术语(terminology), 先以一个员工薪资档(emp.dat ), 来加以介绍.
A125 Jenny 100 210
A341 Dan 110 215
P158 Max 130 209
P148 John 125 220
A123 Linda 95 210
文件中各字段依次为 员工ID, 姓名, 薪资率,及 实际工时. ID中的第一码为部门识别码. “A”,”P”分别表示”组装”及”包装”部门.
本小节着重于说明awk程序的主要架构及工作原理, 并对一些重要的名词辅以必要的解释. 由这部分内容, 读者可体会出awk语言的主要精神及awk与其它语程序言的差异处. 为便于说明, 以条列方式说明于后.
名词定义
数据行: awk从数据文件上读取数据的基本单位.以上列文件emp.dat为例, awk读入的
第一笔数据行是 “A125 Jenny 100 210″
第二笔数据行是 “A341 Dan 110 215″
字段(Field) : 为数据行上被分隔开的子字符串.
以数据行”A125 Jenny 100 210″为例,
第一栏 第二栏 第三栏 第四栏 “A125″ “Jenny” 100 210
一般是以空格符来分隔相邻的字段. ( 参考 : awk 之内建变量”FS” )
补遗
Hello,World
通过演示“Hello,World”这个程序来介绍一种程序设计语言已经成为一种惯例。通过演示这个程序在 awk 中如何工作将证明 awk 是如何的不寻常。实际上,有必要演示几种打印“Hello,World”的不同方法。
在第一个例子中,我们创建了一个文件,命名为 test,它只包含一个句子。这个例子是一个包含 print 语句的脚本:
$ echo 'this line of data is ignored' > test
$ awk '{print "Hello World"}' test
Hello World
这个脚本只有一条包含在大括号中的语句。这个操作对每个输入行执行 print 语句。在本例中,test 文件只包含一行,因此,print 操作只执行一次。注意这个输入行将被输入但没有被输出。
现在让我们看另外一个例子,这里使用一个包含“Hello,World”行的文件。
$ cat test2
Hello,World
$ awk '{print}' test2
Hello,World
在这个例子中,“Hello,World”出现在输入文件中,得到了相同的结果。因为其中的 print 语句没有参数,只简单地输出每个输入行。如果文件中有其他输入行,它们同样可以被输出。
这两个例子都说明了 awk 是输入驱动的。也就是说,除非有可以在其上操作的输入行,否则将什么也不能做。当调用 awk 程序时,它将读入所提供的脚本,并检查其中的指令的语法。然后 awk 将对每个输入行执行脚本中的指令。因此,如果没有来自文件中的输入行,以上的 print 语句将不做任何事情。
为 了验证这一点,可以输入第一个例子中的命令行,但忽略文件名。你将发现由于 awk 期望得到来自键盘的输入,所以它将一直等待直到对它提供了输入:按几次 Enter 键,并用 EOF(大多数系统使用 CTRL-D)作为输入的结束标志。每次按 Enter 键,打印“Hello World”的操作将被执行。
还有另外一种方法来输出“Hello World”信息,并且 awk 不需要等待输入。这个方法的实现和 BEGIN 模式是相关的,BEGIN 模式用于指定在第一个输入行读入之前要执行的动作。
$ awk 'BEGIN {print "Hello,World"}'
Hello,World
awk打印这消息,然后退出程序。如果一个程序只有一个 BEGIN 模式,并且没有其他语句,awk将不处理任何输入文件。
awk 程序设计模型
理 解 awk 提供给程序员的基本模型是很重要的。awk 程序是由所谓的主输入(main input)循环组成的。一个循环是一个例程(routine),它将一直重复执行直到有一些存在的条件终止它。你不必写这个循环,它是现成的。它作为一 个框架存在,在这个框架中你编写的代码能够执行。在awk中的主输入循环是一个例程,它可以从文件中读取一行并使得进程可以访问它。你所编写的处理操作代 码假设有一个可用的输入行。
主输入循环执行的次数和输入的行数相同。就像在“Hello,World”例子中所看到的,这种循环仅当有一个输入行时才执行。当没有其他输入行读入时循环将终止。(输入驱动)
awk 允许你编写两个特殊的例程,它们在任何输入被读取前和所有输入都被读取后执行。它们是与 BEGIN 和 END 规则相关的过程。换句话说,在主输入循环执行前和主输入循环终止后你可以做一些处理。BEGIN 和 END 过程是可选的。
可以把 awk 脚本看做由 3 个主要部分组成:处理输入前将做的处理,处理输入过程中将做的处理,处理输入完成后做的处理。
对 于这 3 个组成部分,主输入循环或称为“处理过程中将做的处理”是主要的处理部分。在主输入循环中,指令被写成一系列的“模式/动作”过程。模式是用于测试输入行 的规则,以确定动作是否将应用于这些输入行(只有与一个特定的模式相匹配的输入行才能成为操作对象。如果没有指定操作,与模式相匹配的输入行将被打印出来 (执行打印语句是一个默认操作))。主输入循环中,所写的过程将应用于每个输入行,而且一次一行(严格来说是应用于每一笔记录,一笔记录不一定只有一行, 这与 awk 的内建变量 FS、RS相关)。