2017-09-28 5 views
0

私のスクリプトは、価格(col $ 3) で食料品リスト(col $ 1)を出力します。そして、それらをカテゴリ($ 2列)で結合し、各カテゴリのコストを追加します。どうやってawkにループを書くのですか?

問題は私がforループを実行しているときに、常に元の食料品リスト出力の最初の行だけが混乱してしまうことです。 別のbegin endでそれらを分離しようとしましたが、動作しません。

ここに私の現在のコードは、サブカテゴリのループがコメントアウトされています。

#!/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

- それは何を理解するのは難しいです – RomanPerekhrest

+0

@RomanPerekhrest私はいくつかのサンプルの入力と出力、感謝を追加しました。 – M2bandit

+1

なぜ「バスルームクリーナー」、「ベーグル/クロワッサン」などが出力から逃したのですか? – RomanPerekhrest

答えて

2

GNUAWKソリューション:

$ 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 
} 
それが生成された入力で

:他のawksと私は非常にあなたが最初(gensubのためのGNU AWKを使って(データを取得をお勧めします

$ 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 
+0

ありがとう、私はドキュメントもありがとう! – M2bandit

+0

ようこそ。 –

1

)と\ S/\ S-は(変数+ [G]サブを使用します)+ [: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 
関連する問題