awkで、特定の列を集計してパーセントを計算した列を追加したいということがあったので、備忘で残しておく。 以下のように、ファイルを2回読み込ませてやり、1回目に集計処理を、2回目に読み込む際にパーセント列の計算をすることで実現できる。

awk 'NR==FNR{a=a+$2;next}{p=$2/a*100;print $0,p"%"}' file file
blacknon@BS-PUB-DEVELOP:~$ cat test2.list
a 4799
b 29975
c 29188
d 31047
e 11659
f 7653
g 19850
h 16754
i 16512
j 15015
k 26007
blacknon@BS-PUB-DEVELOP:~$ # 2列目の内容を集計して3列目にパーセントを表示
blacknon@BS-PUB-DEVELOP:~$ awk 'NR==FNR{a=a+$2;next}{p=$2/a*100;print $0,p"%"}' test2.list test2.list
a 4799 2.30213%
b 29975 14.3793%
c 29188 14.0018%
d 31047 14.8936%
e 11659 5.59295%
f 7653 3.67123%
g 19850 9.52226%
h 16754 8.03707%
i 16512 7.92098%
j 15015 7.20286%
k 26007 12.4758%
blacknon@BS-PUB-DEVELOP:~$ # 見やすく整形する
blacknon@BS-PUB-DEVELOP:~$ awk 'NR==FNR{a=a+$2;next}{p=$2/a*100;print $0,p"%"}' test2.list test2.list | column -t
a  4799   2.30213%
b  29975  14.3793%
c  29188  14.0018%
d  31047  14.8936%
e  11659  5.59295%
f  7653   3.67123%
g  19850  9.52226%
h  16754  8.03707%
i  16512  7.92098%
j  15015  7.20286%
k  26007  12.4758%

で、上記方法だとファイルの読み込みがキモになっているのだが、パイプから受け付けた内容に対してパーセント列を追加するにはどうすればいいのだろうか。 標準入力は一度読み込むと消えてしまうので、()で括ってやって変数に代入する方法を取ることで対応できる。

cat file |(s=$(cat)&&awk 'NR==FNR{a=a+$2;next}{p=$2/a*100;print $0,p"%"}' <(echo -e "$s") <(echo -e "$s"))
blacknon@BS-PUB-DEVELOP:~$ cat test2.list |(s=$(cat)&&awk 'NR==FNR{a=a+$2;next}{p=$2/a*100;print $0,p"%"}' <(echo -e "$s") <(echo -e "$s"))
a 4799 2.30213%
b 29975 14.3793%
c 29188 14.0018%
d 31047 14.8936%
e 11659 5.59295%
f 7653 3.67123%
g 19850 9.52226%
h 16754 8.03707%
i 16512 7.92098%
j 15015 7.20286%
k 26007 12.4758%
blacknon@BS-PUB-DEVELOP:~$ cat test2.list |(s=$(cat)&&awk 'NR==FNR{a=a+$2;next}{p=$2/a*100;print $0,p"%"}' <(echo -e "$s") <(echo -e "$s")) | column -t
a  4799   2.30213%
b  29975  14.3793%
c  29188  14.0018%
d  31047  14.8936%
e  11659  5.59295%
f  7653   3.67123%
g  19850  9.52226%
h  16754  8.03707%
i  16512  7.92098%
j  15015  7.20286%
k  26007  12.4758%
blacknon@BS-PUB-DEVELOP:~$ # ついでに最終行に集計行を出力
blacknon@BS-PUB-DEVELOP:~$ cat test2.list |(s=$(cat)&&awk 'NR==FNR{a=a+$2;next}{p=$2/a*100;print $0,p"%"}END{print "TOTAL",a,"100%"}' <(echo -e "$s") <(echo -e "$s")) | column -t
a      4799    2.30213%
b      29975   14.3793%
c      29188   14.0018%
d      31047   14.8936%
e      11659   5.59295%
f      7653    3.67123%
g      19850   9.52226%
h      16754   8.03707%
i      16512   7.92098%
j      15015   7.20286%
k      26007   12.4758%
TOTAL  208459  100%