Awk 实例,第 3 部分
2014-11-05 16:58
225 查看
通用线程:Awk实例,第3部分 字符串函数和……支票簿? DanielRobbins 总裁兼CEO,GentooTechnologies,Inc. 2001年4月 转载自:IBMdeveloperWorks中国网站
格式化输出 虽然大多数情况下awk的print语句可以完成任务,但有时我们还需要更多。在那些情况下,awk提供了两个我们熟知的老朋友printf()和sprintf()。是的,如同其它许多awk部件一样,这些函数等同于相应的C语言函数。printf()会将格式化字符串打印到stdout,而sprintf()则返回可以赋值给变量的格式化字符串。如果不熟悉printf()和sprintf(),介绍C语言的文章可以让您迅速了解这两个基本打印函数。在Linux系统上,可以输入"man 3printf"来查看printf()帮助页面。 以下是一些awksprintf()和printf()的样本代码。可以看到,它们几乎与C语言完全相同。
awk有许多字符串函数,这是件好事。在awk中,确实需要字符串函数,因为不能象在其它语言(如C、C++和Python)中那样将字符串看作是字符数组。例如,如果执行以下代码:
首先,有一个基本length()函数,它返回字符串的长度。以下是它的使用方法:
现在,我们讨论一些更耐人寻味的函数,首先是match()。match()与index()非常相似,它与index()的区别在于它并不搜索子串,它搜索的是规则表达式。match()函数将返回匹配的起始位置,如果没有找到匹配,则返回0。此外,match()还将设置两个变量,叫作RSTART和RLENGTH。RSTART包含返回值(第一个匹配的位置),RLENGTH指定它占据的字符跨度(如果没有找到匹配,则返回-1)。通过使用RSTART、RLENGTH、substr() 和一个小循环,可以轻松地迭代字符串中的每个匹配。以下是一个match()调用示例:
现在,我们将研究两个字符串替换函数,sub()和gsub()。这些函数与目前已经讨论过的函数略有不同,因为它们确实修改原始字符串。以下是一个模板,显示了如何调用sub():
通过介绍函数split(),我们来汇总一下已讨论过的函数。split()的任务是“切开”字符串,并将各部分放到使用整数下标的数组中。以下是一个split()调用示例:
简短注释--调用length()、sub()或gsub()时,可以去掉最后一个自变量,这样awk将对$0(整个当前行)应用函数调用。要打印文件中每一行的长度,使用以下awk脚本:
几星期前,我决定用awk编写自己的支票簿结算程序。我决定使用简单的tab定界文本文件,以便于输入最近的存款和提款记录。其思路是将这个数据交给awk脚本,该脚本会自动合计所有金额,并告诉我余额。以下是我决定如何将所有交易记录到"ASCIIcheckbook"中:
用于计算当前余额的算法不太难。awk只需要依次读取每一行。如果列出了费用分类帐,但没有收入分类帐(为"-"),那么这一项就是借方。如果列出了收入分类帐,但没有费用分类帐(为"-"),那么这一项就是贷方。而且,如果同时列出了费用和收入分类帐,那么这个金额就是“分类帐转帐”;即,从费用分类帐减去美元金额,并将此金额添加到收入分类帐。此外,所有这些分类帐都是虚拟的,但对于跟踪收入和支出以及预算却非常有用。 代码 现在该研究代码了。我们将从第一行(BEGIN块和函数定义)开始: balance,第1部分
最后三行显示了如何定义自己的awk。格式很简单--输入"function",再输入名称,然后在括号中输入由逗号分隔的参数。在此之后,"{}"代码块包含了您希望这个函数执行的代码。所有函数都可以访问全局变量(如months变量)。另外,awk提供了"return"语句,它允许函数返回一个值,并执行类似于C和其它语言中"return"的操作。这个特定函数将以3个字母字符串格式表示的月份名称转换成等价的数值。例如,以下代码:
财务函数 以下是其它三个执行簿记的函数。我们即将见到的主代码块将调用这些函数之一,按顺序处理支票簿文件的每一行,从而将相应交易记录到awk数组中。有三种基本交易,贷方(doincome)、借方(doexpense)和转帐(dotransfer)。您会发现这三个函数全都接受一个自变量,叫作mybalance。mybalance是二维数组的一个占位符,我们将它作为自变量进行传递。目前,我们还没有处理过二维数组;但是,在下面可以看到,语法非常简单。只须用逗号分隔每一维就行了。 我们将按以下方式将信息记录到"mybalance"中。数组的第一维从0到12,用于指定月份,0代表全年。第二维是四个字母的分类帐,如"food"或"inco";这是我们处理的真实分类帐。因此,要查找全年食品分类帐的余额,应查看mybalance[0,"food"]。要查找6月的收入,应查看mybalance[6,"inco"]。 balance,第2部分
如果研究这些函数,将发现在我的引用中传递了mybalance引用的数组。另外,我们还引用了几个全局变量:curmonth,它保存了当前记录所属的月份的数值,$2(费用分类帐),$3(收入分类帐)和金额($7,美元金额)。调用doincome()和其它函数时,已经为要处理的当前记录(行)正确设置了所有这些变量。 主块 以下是主代码块,它包含了分析每一行输入数据的代码。请记住,由于正确设置了FS,可以用$1引用第一个字段,用$2引用第二个字段,依次类推。调用doincome()和其它函数时,这些函数可以从函数内部访问curmonth、$2、$3和金额的当前值。请先研究代码,在代码之后可以见到我的说明。 balance,第3部分
循环来迭代分类帐列表。 在接着的大约二十行中,我们分析字段$2和$3,并适当记录交易。如果$2=="-"且$3!="-",表示我们有收入,因此调用doincome()。如果是相反的情况,则调用doexpense();如果$2和$3都包含分类帐,则调用dotransfer()。每次我们都将"balance"数组传递给这些函数,从而在这些函数中记录适当的数据。 您还会发现几行代码说“if($5=="Y"),那么将同一个交易记录到balance2中”。我们在这里究竟做了些什么?您将回忆起$5包含"Y"或"N",并记录交易是否已经过帐到帐户。由于仅当过帐了交易时我们才将交易记录到balance2,因此balance2包含了真实的帐户余额,而"balance"包含了所有交易,不管是否已经过帐。可以使用balance2来验证数据项(因为它应该与当前银行帐户余额匹配),可以使用 "balance"来确保没有透支帐户(因为它会考虑您开出的尚未兑现的所有支票)。 生成报表 主块重复处理了每一行记录之后,现在我们有了关于比较全面的、按分类帐和按月份划分的借方和贷方记录。现在,在这种情况下最合适的做法是只须定义生成报表的END块: balance,第4部分
升级 我使用这个程序的更高级版本来管理我的个人和企业财务。我的版本(由于篇幅限制不能在此涵盖)会打印出收入和费用的月度明细分类帐,包括年度总合、净收入和其它许多内容。它甚至以HTML格式输出数据,因此我可以在Web浏览器中查看它。:)如果您认为这个程序有用,我建议您将这些特性添加到这个脚本中。不必将它配置成要记录任何附加信息;所需的全部信息已经在balance和balance2里面了。只要升级END块就万事具备了! 我希望您喜欢本系列。有关awk的详细信息,请参考以下列出的参考资料。 参考资料 请阅读Daniel在developerWorks上发表的awk系列中的前几篇文章:awk实例, 2部分。 如果想看好的老式书籍,O'Reilly的 sed&awk,2ndEdition是极佳选择。 请参考 PatrickHartigan的 awktutorial还包括了实用的awk脚本。 关于作者 DanielRobbins居住在新墨西哥州的Albuquerque。他是 GentooTechnologies,Inc.的总裁兼CEO,GentooLinux(用于PC的高级Linux)和 Portage系统(Linux的下一代移植系统)的创始人。他还是Macmillan书籍CalderaOpenLinuxUnleashed、SuSELinuxUnleashed和 SambaUnleashed的合作者。Daniel自二年级起就与计算机结下不解之缘,那时他首先接触的是Logo程序语言,并沉溺于Pac-Man游戏中。这也许就是他至今仍担任 SONYElectronicPublishing/Psygnosis的首席图形设计师的原因所在。Daniel喜欢与妻子Mary和新出生的女儿Hadassah一起共度时光。可通过 |
相关文章推荐
- Awk 实例,第 3 部分
- Awk 实例,第 3 部分
- Awk 实例,第 3 部分
- sed 实例,第 3 部分
- 通用线程:Awk 实例,第 2部分
- Bash 实例,第 3 部分探讨 ebuild 系统
- sed 实例,第 3 部分
- Bash 实例,第 3 部分:探讨 ebuild 系统
- sed 实例,第 3 部分
- Bash 实例,第 3 部分
- Bash 实例,第 3 部分
- Awk 实例,第 1 部分
- Bash 实例,第 3 部分 探讨 ebuild 系统
- Bash 实例,第 3 部分
- Awk 实例,第 2 部分
- Bash 实例,第 3 部分
- zz 通用线程: awk 实例,第 1 部分
- Awk 实例,第 1 部分
- 文本处理语言awk在线实例极速入门 (全三部分)
- Awk实例 第二部分