次のようなファイルがあります:
paper 3
paper 6
eraser 2
pencil 9
pencil 44
pencil 1
次のように、共通の最初のフィールドを持つ行を合計したいと思います。
paper 9
eraser 2
pencil 54
標準の Unix ユーティリティを使用してこれを行うための便利なワンライナーはありますか? または、それほど標準的ではない Unix ユーティリティでもかまいません。
答え1
これを見てください:
$ echo "$a"
paper 3
paper 6
eraser 2
pencil 9
pencil 44
pencil 1
$ awk '{a[$1]=a[$1]+$2}END{for (i in a) print i,a[i]}' <(echo "$a")
pencil 54
eraser 2
paper 9
<(echo "$a)
を次のように置き換えますfile
:
$ awk '{a[$1]=a[$1]+$2}END{for (i in a) print i,a[i]}' file
答え2
あまり標準的ではないユーティリティでGNU データマッシュ
$ datamash --whitespace groupby 1 sum 2 < file
paper 9
eraser 2
pencil 54
あるいはもっと簡潔に
$ datamash -Wg 1 sum 2 < file
paper 9
eraser 2
pencil 54
答え3
印刷の順序を気にする場合は、次のようにします。
perl -lane '$h{$F[0]}+=$F[1]; $h[-1+keys%h]=$F[0]; END{print "$_ $h{$_}" for @h}'
ハッシュ内の特定の項目の実行中の合計%h
と、配列内での特定の項目の出現順序を維持するという考え方です@h
。ファイルの最後では、配列から順序を取得してハッシュ (キー + 値) を印刷するだけです@h
。
結果
paper 9
eraser 2
pencil 54
答え4
以下は、awk で書かれた、あまり可愛くないワンライナーです。
awk '{ if (prev && prev != $1) { print prev, sum; sum = 0 }; sum += $2; prev = $1 } END { print prev, sum }' < file.txt
最初のフィールドで同じ値を持つ行をグループ化する必要があります。 そうでない場合は、 できますsort file.txt | awk ...
。