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