シェルスクリプト(awk)でCSVデータの行合計、列合計を算出する

2022-01-27AWK,Bash

はじめに

あまり AWK が得意ではないのでエントリで取り扱うことがありませんでしたが、csvファイルの行合計、列合計を求める作業をしたためエントリにまとめました。

検証環境

$ uname -moi
x86_64 MacBookPro16,1 Darwin

$ bash -version | head -n 1
GNU bash, バージョン 5.1.16(1)-release (x86_64-apple-darwin21.1.0)

準備:テスト用のcsvデータ

今回は awk を使って行の合計、列の合計を算出してみようと思います。

算出操作を紹介する際に利用するテストデータを事前に準備します。

適当なデータファイルとして data.csv を作成します。

$ seq 1 30 \
  | xargs -n 5 echo \
  | sed 's/ \+/,/g' >data.csv

作成された data.csv のデータは以下のようになっています。

$ cat data.csv
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
16,17,18,19,20
21,22,23,24,25
26,27,28,29,30

awk で各行の合計を算出する方法

awk コマンドを使い、各行に対して、5列の値を合計し出力してみたいと思います。

$ awk <data.csv -F, '{ sum=0; for (i=1; i<=NF; i++) { sum+=$i } print sum; }'
15
40
65
90
115
140

各列の区切り文字として「カンマ ( , )」を利用したい場合には、 -F, というオプションを指定します。

NF は各行ごとの列数を表す変数です。
今回は NF = 5 となっています。

awk で各列の合計を算出する方法

sum という連想配列に、 各列ごとの合計値を加算していきます。

各行の処理が終了した後、列ごとの合計値を出力します。

出力結果は改行され、5行出力されています。

$ awk <data.csv -F, '{ for (i=1; i<=NF; i++) { sum[i]+=$i } } END { for (i=1; i<=length(sum); i++) { print sum[i] } }'
81
87
93
99
105

(おまけ) q コマンドが使える場合

過去のエントリで取り上げた q コマンドが使える場合は、SQLで集計を行うことができます。

# 各列の合計を算出
$ q -d, "select sum(c1), sum(c2), sum(c3), sum(c4), sum(c5) from data.csv"
81,87,93,99,105

# 各行の合計を算出
$ q -d, "select c1+c2+c3+c4+c5 from data.csv"
15
40
65
90
115
140

# すべての数値の合計を算出
$ q -d, "select sum(c1+c2+c3+c4+c5) from data.csv"
465

ひとこと

ループの開始条件、終了条件を調整すれば、一部の行、列の合計を行うこともできます。


2行目〜4行目の合計を算出

$ cat data.csv
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
16,17,18,19,20
21,22,23,24,25
26,27,28,29,30

$ awk <data.csv -F, '{ sum=0; for (i=1; i<=NF; i++) { sum+=$i } print sum; }' | sed -n '2,4p'
40
65
90

2列目〜4列目の合計を算出

$ cat data.csv
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
16,17,18,19,20
21,22,23,24,25
26,27,28,29,30

$ awk <data.csv -F, '{ for (i=2; i<=4; i++) { sum[i]+=$i } } END { for (i=1; i<=length(sum); i++) { print sum[i] } }'
87
93
99

2022-01-27AWK,Bash