Awk 实例,第 1 部分
2004-11-12 07:45
260 查看
通用线程:Awk 实例,第 1 部分 一种名称很奇特的优秀语言介绍 Daniel Robbins 总裁兼 CEO,Gentoo Technologies, Inc. 2000 年 12 月 转载自:IBM developerWorks 中国网站
捍卫 awk 在本系列文章中,我将使您成为精通 awk 的编码人员。我承认,awk 并没有一个非常好听且又非常“时髦”的名字。awk 的 GNU 版本(叫作 gawk)听起来非常怪异。那些不熟悉这种语言的人可能听说过 "awk", 并可能认为它是一组落伍且过时的混乱代码。它甚至会使最博学的 UNIX 权威陷于错乱的边缘(使他不断地发出 "kill -9!" 命令,就象使用咖啡机一样)。 的确,awk 没有一个动听的名字。但它是一种很棒的语言。awk 适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行需要特殊技巧程序设计。与某些语言不同,awk 的语法较为常见。它借鉴了某些语言的一些精华部分,如 C 语言、python 和 bash(虽然在技术上,awk 比 python 和 bash 早创建)。awk 是那种一旦学会了就会成为您战略编码库的主要部分的语言。 第一个 awk 让我们继续,开始使用 awk,以了解其工作原理。在命令行中输入以下命令:
现在,解释 { print }代码块。在 awk 中,花括号用于将几块代码组合到一起,这一点类似于 C 语言。在代码块中只有一条 print 命令。在 awk 中,如果只出现 print 命令,那么将打印当前行的全部内容。 这里是另一个 awk 示例,它的作用与上例完全相同:
$0变量表示整个当前行,所以 print $0的作用完全一样。 如果您愿意,可以创建一个 awk 程序,让它输出与输入数据完全无关的数据。以下是一个示例:
多个字段 awk 非常善于处理分成多个逻辑字段的文本,而且让您可以毫不费力地引用 awk 脚本中每个独立的字段。以下脚本将打印出您的系统上所有用户帐户的列表:
print $1命令时,它会打印出在输入文件中每一行中出现的第一个字段。以下是另一个示例:
print $1 $3命令在两个字段之间插入空格。然而,当两个字符串在 awk 程序中彼此相邻时,awk 会连接它们但不在它们之间添加空格。以下命令会在这两个字段中插入空格:
$1、" " 和 $3,创建 可读的输出。当然,如果需要的话,我们还可以插入一些文本标签:
将脚本作为命令行自变量传递给 awk 对于小的单行程序来说是非常简单的,而对于多行程序,它就比较复杂。您肯定想要在外部文件中撰写脚本。然后可以向 awk 传递 -f 选项,以向它提供此脚本文件:
BEGIN 和 END 块 通常,对于每个输入行,awk 都会执行每个脚本代码块一次。然而,在许多编程情况中,可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况,awk 允许您定义一个 BEGIN 块。我们在前一个示例中使用了 BEGIN 块。因为 awk 在开始处理输入文件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。 awk 还提供了另一个特殊块,叫作 END 块。awk 在处理了输入文件中的所有行之后执行这个块。通常,END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。 规则表达式和块 awk 允许使用规则表达式,根据规则表达式是否匹配当前行来选择执行独立代码块。以下示例脚本只输出包含字符序列 foo的那些行:
还有许多其它方法可以选择执行代码块。我们可以将任意一种布尔表达式放在一个代码块之前,以控制何时执行某特定块。仅当对前面的布尔表达式求值为真时, awk 才执行代码块。以下示例脚本输出将输出其第一个字段等于 fred的所有行中的第三个字段。如果当前行的第一个字段不等于 fred,awk 将继续处理文件而不对当前行执行
root, 那么以下示例将只打印这一行中的第三个字段:
awk 还提供了非常好的类似于 C 语言的 if语句。如果您愿意,可以使用 if语句重写前一个脚本:
if语句来选择执行 print 命令。这两个方法都可以使用,可以选择最适合脚本其它部分的一种方法。 以下是更复杂的 awk if语句示例。可以看到,尽管使用了复杂、嵌套的条件语句, if语句看上去仍与相应的 C 语言 if语句一样:
if语句还可以将代码:
matchme字符序列的那些行。此外,还可以选择最适合您的代码的方法。它们的功能完全相同。 awk 还允许使用布尔运算符 "||"(逻辑与)和 "&&"(逻辑或),以便创建更复杂的布尔表达式:
foo且第二个字段等于 bar的那些行。 数值变量! 至今,我们不是打印字符串、整行就是特定字段。然而,awk 还允许我们执行整数和浮点运算。通过使用数学表达式,可以很方便地编写计算文件中空白行数量的脚本。以下就是这样一个脚本:
x初始化成零。然后,awk 每次遇到空白行时,awk 将执行 x=x+1语句,递增 x。处理完所有行之后,执行 END 块,awk 将打印出最终摘要,指出它找到的空白行数量。 字符串化变量 awk 的优点之一就是“简单和字符串化”。我认为 awk 变量“字符串化”是因为所有 awk 变量在内部都是按字符串形式存储的。同时,awk 变量是“简单的”,因为可以对它执行数学操作,且只要变量包含有效数字字符串,awk 会自动处理字符串到数字的转换步骤。要理解我的观点,请研究以下这个示例:
1.01赋值给变量 x,我们仍然可以对它加 一。但在 bash 和 python 中却不能这样做。首先,bash 不支持浮点运算。而且,如果 bash 有“字符串化”变量,它们并不“简单”;要执行任何数学操作,bash 要求我们将数字放到丑陋的 $( )) 结构中。如果使用 python,则必须在对 1.01字符串执行任何数学运算之前,将它转换成浮点值。虽然这并不困难,但它仍是附加的步骤。如果使用 awk,它是全自动的,而那会使我们的代码又好又整洁。如果想要对每个输入行的第一个字段乘方并加一,可以使用以下脚本:
众多运算符 awk 的另一个优点是它有完整的数学运算符集合。除了标准的加、减、乘、除,awk 还允许使用前面演示过的指数运算符 "^"、模(余数)运算符 "%" 和其它许多从 C 语言中借入的易于使用的赋值操作符。 这些运算符包括前后加减( i++、 --foo)、加/减/乘/除赋值运算符( a+=3、 b*=2、 c/=2.2、 d-=6.2)。不 仅如此 -- 我们还有易于使用的模/指数赋值运算符( a^=2、 b%=4)。 字段分隔符 awk 有它自己的特殊变量集合。其中一些允许调整 awk 的运行方式,而其它变量可以被读取以收集关于输入的有用信息。我们已经接触过这些特殊变量中的一个,FS。前面已经提到过,这个变量让您可以设置 awk 要查找的字段之间的字符序列。我们使用 /etc/passwd 作为输入时,将 FS 设置成 ":"。当这样做有问题时,我们还可以更灵活地使用 FS。 FS 值并没有被限制为单一字符;可以通过指定任意长度的字符模式,将它设置成规则表达式。如果正在处理由一个或多个 tab 分隔的字段,您可能希望按以下方式设置 FS:
如果字段由空格分隔(一个或多个空格或 tab),您可能想要将 FS 设置成以下规则表达式:
复杂的规则表达式也不成问题。即使您的记录由单词 "foo" 分隔,后面跟着三个数字,以下规则表达式仍允许对数据进行正确的分析:
接着我们要讨论的两个变量通常并不是需要赋值的,而是用来读取以获取关于输入的有用信息。第一个是 NF 变量,也叫做“字段数量”变量。awk 会自动将该变量设置成当前记录中的字段数量。可以使用 NF 变量来只显示某些输入行:
记录号 (NR) 是另一个方便的变量。它始终包含当前记录的编号(awk 将第一个记录算作记录号 1)。迄今为止,我们已经处理了每一行包含一个记录的输入文件。对于这些情况,NR 还会告诉您当前行号。然而,当我们在本系列以后部分中开始处理多行记录时,就不会再有这种情况,所以要注意!可以象使用 NF 变量一样使用 NR 来只打印某些输入行:
现在已经到了初次探索 awk 的尾声。随着本系列的开展,我将演示更高级的 awk 功能,我们将用一个真实的 awk 应用程序作为本系列的结尾。同时,如果急于学习更多知识,请参考以下列出的参考资料。 参考资料 如果想看好的老式书籍,O'Reilly 的 sed & awk, 2ndEdition 是极佳选择。 请参考 comp.lang.awkFAQ。它还包含许多附加 awk 链接。 Patrick Hartigan 的 awk tutorial 还包括了实用的 awk 脚本。 Thompson's TAWKCompiler 将 awk 脚本编译成快速二进制可执行文件。可用版本有 Windows 版、OS/2 版、DOS 版和 UNIX 版。 The GNUAwk User's Guide 可用于在线参考。 关于作者 Daniel Robbins 居住在新墨西哥州的 Albuquerque。他是 Gentoo Technologies, Inc. 的总裁兼 CEO,Gentoo Linux(用于 PC 的高级 Linux)和 Portage 系统(Linux 的下一代移植系统)的创始人。他还是 Macmillan 书籍 Caldera OpenLinux Unleashed、SuSE Linux Unleashed 和 Samba Unleashed 的合作者。Daniel 自二年级起就与计算机某些领域结下不解之缘,那时他首先接触的是 Logo 程序语言,并沉溺于 Pac-Man 游戏中。这也许就是他至今仍担任 SONY Electronic Publishing/Psygnosis 的首席图形设计师的原因所在。Daniel 喜欢与妻子 Mary 和新出生的女儿 Hadassah 一起共度时光。可通过 drobbins@gentoo.org 与 Daniel 联系。 |
相关文章推荐
- Awk 实例,第 3 部分
- 通用线程:Awk 实例,第 2部分
- Awk实例 第三部分(系列结束)
- Awk 实例,第 1 部分
- Awk实例 第二部分
- Awk 实例,第 2 部分
- awk的使用 第六部分 awk编程的几个实例
- Awk 实例,第 1 部分
- awk使用 第7部分 awk对多行数据的处理实例
- 通用线程:Awk 实例,第 1部分
- Awk 实例,第 3 部分
- 通用线程:Awk 实例,第 2部分
- Awk 实例,第 2 部分
- Awk 实例,第 1 部分
- 文本处理语言awk在线实例极速入门 (全三部分)
- Awk 实例,第 2 部分
- zz 通用线程: awk 实例,第 1 部分
- Awk 实例,第 3 部分
- Awk 实例,第 2 部分
- Awk 实例,第 3 部分