分类:
2009-08-15 16:51:11
balance,第 3 部分
{ curmonth=monthdigit(substr($1,4,3)) amount=$7 #record all the categories encountered if ( $2 != "-" ) globcat[$2]="yes" if ( $3 != "-" ) globcat[$3]="yes" #tally up the transaction properly if ( $2 == "-" ) { if ( $3 == "-" ) { print "Error: inc and exp fields are both blank!" exit 1 } else { #this is income doincome(balance) if ( $5 == "Y" ) doincome(balance2) } } else if ( $3 == "-" ) { #this is an expense doexpense(balance) if ( $5 == "Y" ) doexpense(balance2) } else { #this is a transfer dotransfer(balance) if ( $5 == "Y" ) dotransfer(balance2) } }
在主块中,前两行将 curmonth 设置成 1 到 12 之间的整数,并将金额设置成字段 7(使代码易于理解)。然后,是四行有趣的代码,它们将值写到数组 globcat 中。globcat,或称作全局分类帐数组,用于记录在文件中遇到的所有分类帐 -- "inco"、"misc"、"food"、"util" 等。例如,如果 $2 == "inco",则将 globcat["inco"] 设置成 "yes"。稍后,我们可以使用简单的 "for (x in globcat)" 循环来迭代分类帐列表。
在接着的大约二十行中,我们分析字段 $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 部分
END { bal=0 bal2=0 for (x in globcat) { bal=bal+balance[0,x] bal2=bal2+balance2[0,x] } printf("Your available funds: %
这个报表将打印出汇总,如下所示:
Your available funds:1174.22Your account balance:2399.33
在 END 块中,我们使用 "for (x in globcat)" 结构来迭代每一个分类帐,根据记录在案的交易结算主要余额。实际上,我们结算两个余额,一个是可用资金,另一个是帐户余额。要执行程序并处理您在文件 "mycheckbook.txt" 中输入的财务数据,将以上所有代码放入文本文件 "balance",执行 "chmod +x balance",然后输入 "./balance mycheckbook.txt"。然后 balance 脚本将合计所有交易,打印出两行余额汇总。
升级
我使用这个程序的更高级版本来管理我的个人和企业财务。我的版本(由于篇幅限制不能在此涵盖)会打印出收入和费用的月度明细分类帐,包括年度总合、净收入和其它许多内容。它甚至以 HTML 格式输出数据,因此我可以在 Web 浏览器中查看它。:) 如果您认为这个程序有用,我建议您将这些特性添加到这个脚本中。不必将它配置成要 记录任何附加信息;所需的全部信息已经在 balance 和 balance2 里面了。只要升级 END 块就万事具备了!
我希望您喜欢本系列。有关 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 的首席图形设计师的原因所在。