2013-06-13 13 views
6

私のテーブルファイルの例を行うことawkの文 - 見つからない場合(に読まれる)

Name1 xxxxx 34 
Name1 xxxxx 37 
Name2 aaaaa 59 
Name2 xxxxx 90 
Name4 Name3 12 

名のファイルは、私はawk名前のファイルからName1/2/3/4を一致させたいという

Name1 
Name2 
Name3 
Name4 

のように見えるようになります。テーブルファイル$ 1と$ 3のプリント合計に変換します。 名前が見つからない場合0 - どうすればいいですかifawkに記載されていますか?

私はすでに行わ:

for i in $(cat Name_file) 
do 
cat table | awk -v NAME="$i" '($1==NAME) {SUM+=$3} END {print NAME"\t"SUM}' 
done 

が出力に

Name1 71 
Name2 149 
Name3 
Name4 12 

を与えることはほぼ完璧だ - 私は

Name1 71 
Name2 149 
Name3 0 
Name4 12 

このような出力を得るためにName30を追加したいので、多くの質問どのようにif not found do関数をawkに追加するのですか?

+2

私は[:bashのタグ]に代わりに '' $(猫ファイル)の '' $(<ファイル)を使用することを示唆しています。最初の表記は外部ユーティリティを呼び出さない。また 'cat file | 'の代わりに' awk' ... 'file'を使います。 awk '...' '。 – TrueY

+1

あなたは '$()のiの意味ですか?あなたの提案と 'read WORDの間の違いは何ですか?コマンドを実行します。完了

+1

はい、 '$()を使用してください。 '$(cat Name_file)'のための内部的な 'bash'ショートカットです。だから 'cat'を呼び出さず、ファイルを開くだけです。 'read'内部関数は、' TrueY

答えて

1

するTry SG:

awk 'NR==FNR{a[$1]=0;next}$1 in a{a[$1]+=$3}END{for(i in a) print i,a[i]}' Name_file table 

出力:この場合

Name1 71 
Name2 149 
Name3 0 
Name4 12 

あなたは周りループを必要としません。それは最初にNames_tableを読み取り、tableのすべての行を1つのステップで処理します。だからはるかに効果的です。

拡張質問は$1$2によってグループにあったEXTENDED

printf -v tmp "[%s]=0 " $(<Name_file) 
declare -A htmp 
eval htmp=($tmp) 
while read a b c; do [ -n "${htmp[$a]}" ] && ((htmp[$a] += $c)); done <table 
for i in ${!htmp[*]}; do echo $i ${htmp[$i]}; done 

(及びName_file含ま:

または純粋(> = 4.0)溶液を添加しましたtableからのすべての最初のキーですので、実際はありません処理する必要があります)。

cat >table <<XXX 
Name1 xxxxx 34 
Name1 xxxxx 37 
Name2 aaaaa 59 
Name2 xxxxx 90 
Name4 Name3 12 
XXX 

awk -v SUBSEP=, '{a[$1,$2]+=$3;++n[$1,$2]}END{for(i in a) print i,a[i],n[i]}' table 

出力:

Name2,xxxxx 90 1 
Name2,aaaaa 59 1 
Name4,Name3 12 1 
Name1,xxxxx 71 2 
+2

あなたのメソッドは、名前にリストされているだけでなく、すべての行の合計を出力します。正しく動作させるには '($ 1 in a)'条件を追加する必要があります。また、それは望ましくない可能性のあるランダムな順序でカウントを出力します。 – Vovanium

+0

@Vovanium:ありがとう!追加されました。実際にそれは仕様ではなかった... :) – TrueY

+0

私はもう一つ質問があるので私は私の元の質問 'テーブル'を編集しました。あなたのコードがすべての一意のName_file単語に対してループし、$ 3を追加すると、一意の$ 1単語(Name1 xxxx、Name2 aaaa、Name2 xxxxなどのフォームグループ)ごとに一意の$ 2単語を区別し、グループごとに3ドル?このような結果を得るには、 'Name1 xxxx 71 2'、 'Name2 aaaa 59 1'、' Name2 xxxx 90 1'? $ 4は、グループを構成するためにマージされた単語の数を示します。もしそれが多すぎるなら、私はこれを新しい質問として投稿することができます。 –

2

Yは「見つからない」動作を必要としません。カウントする前に変数SUMが正しく初期化されていません。それにはBEGIN {SUM = 0}を使用してください。

明示的に/見つからない動作が必要な場合は、同様に行います。まず、変数BEGIN {FOUND = 0}を初期化し、パターン一致で何らかの方法でそれを変更します:(...) {FOUND = FOUND+1}と最後にif(FOUND!=0)でテストしてください。このような

+0

チャア!だからシンプル:)ありがとう。 –

関連する問題