我的脚本输出一个价格(col $ 3)的购物清单(col $ 1) 然后它按类别(第2列)组合它们并添加每个类别的成本。
问题是,当我运行for循环时,它总是与原始杂货清单输出的第一行混淆。 我尝试在不同的开始端分离它们,但它不起作用。
这是我当前的代码,子类别的循环被注释掉了。
#!/bin/awk
BEGIN { FS="\t+"; OFS=" "; printf("%-30s %s\n", "Item","Cost")
printf("%-30s %s\n", "====","====")}
{ printf("%-30s %s\n", $2, $3, 30) }
END {
}
#BEGIN {
#}
#NR==1{print;next}
#{a[$1]+=substr($3, 2)}
#END { for(i in a)printf("%-30s %s\n", i, a[i], 30)
#}
输出样本:
Item Cost
==== ======
Air freshener $10.60
Antiperspirant / Deodorant $03.80
Apples $10.80
Asparagus $01.05
Avocados $08.25
BBQ sauce $08.55
Baby food $08.60
Baby wash $05.40
Subtotal by Category
---------------------------
Alcohol $ 76.10
Baby/Pet $ 81.55
Baking $ 54.15
Bread $ 50.20
Canned goods $ 55.60
Chips/Crackers $ 53.65
Cleaner/Detergent $ 46.75
Condiments $ 92.40
Dairy $ 46.30
Produce $195.45
Soap/Sundry $113.65
Spices $ 89.40
===========================
Total $955.20
输入样本:
Cleaner/Detergent Air freshener $10.60
Soap/Sundry Antiperspirant / Deodorant $03.80
Produce Apples $10.80
Produce Asparagus $01.05
Produce Avocados $08.25
Condiments BBQ sauce $08.55
Baby/Pet Baby food $08.60
Baby/Pet Baby wash $05.40
Bread Bagels / Croissants $10.35
Baking Baking powder / Soda $07.85
Produce Bananas $02.90
Spices Basil $01.70
Soap/Sundry Bath soap / Hand soap $06.75
Cleaner/Detergent Bathroom cleaner $04.55
答案 0 :(得分:2)
GNU awk 解决方案,可以一气呵成:
$ cat tst.awk
#!/bin/awk
BEGIN {
FS="\t+";OFS=" "
}
NF==3{ # check if there are fields
amount=substr($3,2)
l1=length($1); l2=length($2) # save max length of 1st col
col1=(l1<l2)?(col1<l2?l2:col1):(col1<l1?l1:col1) # in col1
a[$2]=($2 in a? a[$2]+amount : amount) # item as key, amount as value
total=total+amount # save total, for col2 width
c[$1]=c[$1]+amount # save sum per category
}
END {
col2=length(total) # determine col2 width
printf "%-*s%s%s\n", col1, "Item", OFS, "Cost" # print header item table
printf "%s%s%s\n", separator("=",col1), OFS, separator("=",col2+2)
PROCINFO["sorted_in"]="@ind_str_asc" # define sorting order
for(i in a) # print Item table
printf "%-*s%s$ %*.2f\n", col1, i, OFS, col2, a[i]
printf "\n%s\n", "Subtotal by Category" # print header category table
print separator("-", col1+col2+length(OFS)+2) # "+2" because of "$ "
for (j in c) # print category table
printf "%-*s%s$ %*.2f\n", col1, j, OFS, col2, c[j]
print separator("=", col1+col2+length(OFS)+2) # "+2" because of "$ "
printf "%-*s%s$ %*.2f\n", col1, "Total", OFS, col2, total # print total
}
func separator(sep,n){ # function for generating
s=sprintf("%*s",n,""); gsub(/ /,sep,s); return s # separator line
}
使用提供的输入生成:
$ awk -f tst.awk input.txt
Item Cost
========================== =======
Air freshener $ 10.60
Antiperspirant / Deodorant $ 3.80
Apples $ 10.80
Asparagus $ 1.05
Avocados $ 8.25
BBQ sauce $ 8.55
Baby food $ 8.60
Baby wash $ 5.40
Bagel / Croissants $ 10.35
Baking powder / Soda $ 7.85
Bananas $ 2.90
Basil $ 1.70
Bath soap / Hand soap $ 6.75
Bathroom cleaner $ 4.55
Subtotal by Category
------------------------------------
Baby/Pet $ 14.00
Baking $ 7.85
Bread $ 10.35
Cleaner/Detergent $ 15.15
Condiments $ 8.55
Produce $ 23.00
Soap/Sundry $ 10.55
Spices $ 1.70
====================================
Total $ 91.15
答案 1 :(得分:1)
我强烈建议你先获取数据(使用GNU awk for gensub()和\ S / \ s-,其他awks使用变量+ [g] sub()+ [:space:]):
$ cat tst.awk
BEGIN { OFS="\t" }
{
cat = $1
item = gensub(/^\S+\s+|\s+\S+$/,"","g")
cost = gensub(/\$/,"",1,$NF)
print "Item", item, cost
subTot[cat] += cost
tot += cost
}
END {
for (cat in subTot) {
print "Category", cat, subTot[cat]
}
print "Total", "Total", tot
}
$ awk -f tst.awk file
Item Air freshener 10.60
Item Antiperspirant / Deodorant 03.80
Item Apples 10.80
Item Asparagus 01.05
Item Avocados 08.25
Item BBQ sauce 08.55
Item Baby food 08.60
Item Baby wash 05.40
Item Bagels / Croissants 10.35
Item Baking powder / Soda 07.85
Item Bananas 02.90
Item Basil 01.70
Item Bath soap / Hand soap 06.75
Item Bathroom cleaner 04.55
Category Spices 1.7
Category Baby/Pet 14
Category Condiments 8.55
Category Produce 23
Category Soap/Sundry 10.55
Category Baking 7.85
Category Bread 10.35
Category Cleaner/Detergent 15.15
Total Total 91.15
然后您可以将其读入电子表格和/或编写您喜欢的任何格式化脚本以提供布局,例如:
$ awk -f tst.awk file |
awk 'BEGIN{FS=OFS="\t"} $1!=p{print "_" ORS $1, "Cost" ORS "====", "===="; p=$1} {print $2, "$"$3}' |
column -s$'\t' -t
_
Item Cost
==== ====
Air freshener $10.60
Antiperspirant / Deodorant $03.80
Apples $10.80
Asparagus $01.05
Avocados $08.25
BBQ sauce $08.55
Baby food $08.60
Baby wash $05.40
Bagels / Croissants $10.35
Baking powder / Soda $07.85
Bananas $02.90
Basil $01.70
Bath soap / Hand soap $06.75
Bathroom cleaner $04.55
_
Category Cost
==== ====
Spices $1.7
Baby/Pet $14
Condiments $8.55
Produce $23
Soap/Sundry $10.55
Baking $7.85
Bread $10.35
Cleaner/Detergent $15.15
_
Total Cost
==== ====
Total $91.15