我们将按以下方式将信息记录到 "mybalance" 中 。数组的第一维从 0 到 12,用于指定月份,0 代表全年 。第二维是四个字母的分类帐,如 "food" 或 "inco";这是我们处理的真实分类帐 。因此,要查找全年食品分类帐的余额,应查看 mybalance[0,"food"] 。要查找 6 月的收入,应查看 mybalance[6,"inco"] 。
balance,第 2 部分
function doincome(mybalance) { mybalance[curmonth,$3]= amount mybalance[0,$3]= amount}function doexpense(mybalance) { mybalance[curmonth,$2] -= amount mybalance[0,$2] -= amount}function dotransfer(mybalance) { mybalance[0,$2] -= amount mybalance[curmonth,$2] -= amount mybalance[0,$3]= amount mybalance[curmonth,$3]= amount}
调用 doincome() 或任何其它函数时,我们将交易记录到两个位置 -- mybalance[0,category] 和 mybalance[curmonth, category],它们分别表示全年的分类帐余额和当月的分类帐余额 。这让我们稍后可以轻松地生成年度或月度收入/支出明细分类帐 。
如果研究这些函数,将发现在我的引用中传递了 mybalance 引用的数组 。另外,我们还引用了几个全局变量:curmonth,它保存了当前记录所属的月份的数值,$2(费用分类帐),$3(收入分类帐)和金额($7,美元金额) 。调用 doincome() 和其它函数时,已经为要处理的当前记录(行)正确设置了所有这些变量 。
主块
以下是主代码块,它包含了分析每一行输入数据的代码 。请记住,由于正确设置了 FS,可以用 $ 1 引用第一个字段,用 $2 引用第二个字段,依次类推 。调用 doincome() 和其它函数时,这些函数可以从函数内部访问 curmonth、$2、$3 和金额的当前值 。请先研究代码,在代码之后可以见到我的说明 。
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 块:
推荐阅读
- 通用线程--sed 实例,第3部分
- 通用线程--sed 实例,第1部分
- 通用线程--sed 实例,第2部分
- FreeBSD下设置modem和modem的通用命令
- 什么叫多线程
- 和彩云支持普通用户上传多大文件
- 缝好衣服后怎么用短线快速打结?男女通用
- 医保是全国通用的吗
- 5e和steam皮肤通用吗
- 下 Solaris 10通用桌面CDE快速入门