Awk释义英文原义:Aho、Weinberger、Kernighan
中文释义:三位创造者Aho、Weinberger和Kernighan统称
Awk简介AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。 AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
最简单地说, AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法。它的设计思想来源于 SNOBOL4 、sed 、Marc Rochkind设计的有效性语言、语言工具 yacc 和 lex ,当然还从 C 语言中获取了一些优秀的思想。在最初创造 AWK 时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。
尽管操作可能会很复杂,但命令的语法始终是:
awk '{pattern + action}'
其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。
gawk 是 AWK 的 GNU 版本。
一般的UNIX作业系统,本身即附有AWK,不同的UNIX作业系统所附的AWK其版本亦不尽相同,若读者所使用的系统上未附有AWK,可通过 anonymous ftp 到下列地方取得:
phi.sinica.edu.tw:/pub/gnu
ftp.edu.tw:/UNIX/gnu
prep.ai.mit.edu:/pub/gnu
注 解:一种编程语言,因其模式匹配语法而特别有用,通常用于数据检索和数据转换。一个GNU版本称为Gawk。
Awk的调用方式awk提供了适应多种需要的不同解决方案,它们是:
一、 awk命令行,你可以象使用普通UNIX命令一样使用awk,在命令行中你也可以使用awk程序设计语言,虽然awk支持多行的录入,但是录入长长的命令行并保证其正确无误却是一件令人头疼的事,因此,这种方法一般只用于解决简单的问题。当然,你也可以在shell script程序中引用awk命令行甚至awk程序脚本。
二、使用-f选项调用awk程序。awk允许将一段awk程序写入一个文本文件,然后在awk命令行中用-f选项调用并执行这段程序。具体的方法我们将在后面的awk语法中讲到。
三、利用命令解释器调用awk程序:利用UNIX支持的命令解释器功能,我们可以将一段awk程序写入文本文件,然后在它的第一行加上:
#!/bin/awk -f
并赋予这个文本文件以执行的权限。这样做之后,你就可以在命令行中用类似于下面这样的方式调用并执行这段awk程序了。
awk脚本文本名 待处理文件
Awk的语法与其它UNIX命令一样,awk拥有自己的语法:
awk [ -F re] [parameter...] ['prog'] [-f progfile]
参数说明:
-F re:允许awk更改其字段分隔符。
parameter: 该参数帮助为不同的变量赋值。
'prog': awk的程序语句段。这个语句段必须用单拓号:'和'括起,以防被shell解释。这个程序语句段的标准形式为:
'pattern '
其中pattern参数可以是egrep正则表达式中的任何一个,它可以使用语法/re/再加上一些样式匹配技巧构成。与sed类似,你也可以使用"," 分开两样式以选择某个范围。关于匹配的细节,你可以参考附录,如果仍不懂的话,找本UNIX书学学grep和sed(本人是在学习ed时掌握匹配技术的)。 action参数总是被大括号包围,它由一系统awk语句组成,各语句之间用";"分隔。awk解释它们,并在pattern给定的样式匹配的记录上执行其操作。与shell类似,你也可以使用“#”作为注释符,它使“#”到行尾的内容成为注释,在解释执行时,它们将被忽略。你可以省略pattern和 action之一,但不能两者同时省略,当省略pattern时没有样式匹配,表示对所有行(记录)均执行操作,省略action时执行缺省的操作——在标准输出上显示。
-f progfile:允许awk调用并执行progfile指定有程序文件。progfile是一个文本文件,他必须符合awk的语法。
in_file:awk的输入文件,awk允许对多个输入文件进行处理。值得注意的是awk不修改输入文件。如果未指定输入文件,awk将接受标准输入,并将结果显示在标准输出上。awk支持输入输出重定向。
Awk的记录、字段与内置变量前面说过,awk处理的工作与数据库的处理方式有相同之处,其相同处之一就是awk支持对记录和字段的处理,其中对字段的处理是grep和sed不能实现的,这也是awk优于二者的原因之一。在awk中,缺省的情况下总是将文本文件中的一行视为一个记录,而将一行中的某一部分作为记录中的一个字段。为了操作这些不同的字段,awk借用shell的方法,用1,2,3...这样的方式来顺序地表示行(记录)中的不同字段。特殊地,awk用0表示整个行(记录)。不同的字段之间是用称作分隔符的字符分隔开的。系统默认的分隔符是空格。awk允许在命令行中用-F re的形式来改变这个分隔符。事实上,awk用一个内置的变量FS来记忆这个分隔符。awk中有好几个这样的内置变量,例如,记录分隔符变量RS、当前工作的记录数NR等等,本文后面的附表列出了全部的内置变量。这些内置的变量可以在awk程序中引用或修改,例如,你可以利用NR变量在模式匹配中指定工作范围,也可以通过修改记录分隔符RS让一个特殊字符而不是换行符作为记录的分隔符。
例:显示文本文件myfile中第七行到第十五行中以字符%分隔的第一字段,第三字段和第七字段:
awk -F % 'NR==7,NR==15 {printf 1 3 7}'
Awk的内置函数awk 之所以成为一种优秀的程序设计语言的原因之一是它吸收了某些优秀的程序设计语言(例如C)语言的许多优点。这些优点之一就是内置函数的使用,awk定义并支持了一系列的内置函数,由于这些函数的使用,使得awk提供的功能更为完善和强大,例如,awk使用了一系列的字符串处理内置函数(这些函数看起来与C 语言的字符串处理函数相似,其使用方式与C语言中的函数也相差无几),正是由于这些内置函数的使用,使awk处理字符串的功能更加强大。本文后面的附录中列有一般的awk所提供的内置函数,这些内置函数也许与你的awk版本有些出入,因此,在使用之前,最好参考一下你的系统中的联机帮助。
作为内置函数的一个例子,我们将在这里介绍awk的printf函数,这个函数使得awk与c语言的输出相一致。实际上,awk中有许多引用形式都是从C 语言借用过来的。如果你熟悉C语言,你也许会记得其中的printf函数,它提供的强大格式输出功能曾经带我们许多的方便。幸运的是,我们在awk中又和它重逢了。awk中printf几乎与C语言中一模一样,如果你熟悉C语言的话,你完全可以照C语言的模式使用awk中的printf。因此在这里,我们只给出一个例子,如果你不熟悉的话,请随便找一本C语言的入门书翻翻。
例:显示文件myfile中的行号和第3字段:
awk '{printf"%03d%s
",NR,1}' myfile
Awk的命令行使用按照顺序,我们应当讲解awk程序设计的内容了,但在讲解之前,我们将用一些例子来对前面的知识进行回顾,这些例子都是在命令行中使用的,由此我们可以知道在命令行中使用awk是多么的方便。这样做的原因一方面是为下面的内容作铺垫,另一方面是介绍一些解决简单问题的方法,我们完全没有必要用复杂的方法来解决简单的问题----既然awk提供了较为简单的方法的话。
例:显示文本文件mydoc匹配(含有)字符串"sun"的所有行。
awk '/sun/' mydoc
由于显示整个记录(全行)是awk的缺省动作,因此可以省略action项。
awk '/sun/' mydoc
例:下面是一个较为复杂的匹配的示例:
awk '/[Ss]un/,/[Mm]oon/ ' myfile
它将显示第一个匹配Sun或sun的行与第一个匹配Moon或moon的行之间的行,并显示到标准输出上。
例:下面的示例显示了内置变量和内置函数length()的使用:
awk 'length($0)>80 {print NR}' myfile
该命令行将显示文本myfile中所有超过80个字符的行号,在这里,用0表示整个记录(行),同时,内置变量NR不使用标志符''。
例:作为一个较为实际的例子,我们假设要对UNIX中的用户进行安全性检查,方法是考察/etc下的passwd文件,检查其中的passwd字段(第二字段)是否为"*",如不为"*",则表示该用户没有设置密码,显示出这些用户名(第一字段)。我们可以用如下语句实现:
#awk -F: '$2=="" {printf("%s no password!
",1' /etc/passwd
在这个示例中,passwd文件的字段分隔符是“:”,因此,必须用-F:来更改默认的字段分隔符,这个示例中也涉及到了内置函数printf的使用。
awk内置变量详细介绍
awk提供了有很多内置变量,如果你经常使用awk处理文本,了解这些这些内置变量的使用是很有必要的。下面看一下这些内置变量的详细介绍。
ARGC 命令行参数个数(不包括awk的选项和awk的程序内容)
ARGIND 当前正在处理的ARGV中的文件的索引值(同时处理多个文件时会用到)
ARGV 命令行参数序列数组,下标从0开始
CONVFMT 数字转换格式,和C语言中的数字输出格式化类似, 默认为"%.6g"
ENVIRON 当前系统的环境变量
ERRNO 出错时的错误信息
FIELDWIDTHS 以空格分隔的字段宽度,如果指定此变量,awk将会用指定的宽度替换变量FS指定的分隔符。看下面的例子:
[LinuxSong@test /tmp]$ cat t
abcdefasfa
abcdefasfa
abcdefasfa
[LinuxSong@test /tmp]$ awk 'BEGIN {FIELDWIDTHS="2 3 4"}{print $1,$2,$3}' t
ab cde fasf
ab cde fasf
ab cde fasf
FILENAME 当前正在处理的文件名,该变量不能在BEGIN块中使用。
FNR 当前处理的记录号
FS 字段的分隔符,默认为空格。
IGNORECASE 如果该变量设置为非0值,在进行字符串匹配时忽略大小写。
NF 当前记录中的字段个数
NR 已经读出的记录数
OFMT 数字的输出格式
OFS 输出的字段分隔符,默认为空格
ORS 输出的记录分隔符,默认为新行
RS 输入记录的分隔符,默认为新行
RSTART 被match()函数匹配的字符串的起始位置,如果没有匹配则为0(从1开始)
RLENGTH 被match()函数匹配的字符串的长度
SUBSEP 数组中多个下标的分隔符,默认为"