先ほどの成績ファイルの例、score.csv
を元に、フィルタプログラムだけを利用して、合計点の高い順に並べ替えてみよう。
山田太郎,50,70,20 公益太郎,90,80,70 飯森花子,91,79,72 鶴岡一人,60,60,40 酒田三吉,52,70,80 三川一二三,12,34,99
これはCSVファイルなので、各フィールドに分解するにはawkコマンドを
使えばよい。区切りがカンマなので、awkのオプションに -F,
を指定するとカンマでフィールド分解をしてくれる。
「cat score.csv | awk -F,
...」
としたときにawk変数に入る各フィールドは以下の表のようになる。
$1に入るもの | $2に入るもの | $3に入るもの | $4に入るもの |
---|---|---|---|
山田太郎 | 50 | 70 | 20 |
公益太郎 | 90 | 80 | 70 |
飯森花子 | 91 | 79 | 72 |
鶴岡一人 | 60 | 60 | 40 |
酒田三吉 | 52 | 70 | 80 |
三川一二三 | 12 | 36 | 99 |
各レコードについて、合計点を求めるには、$2, $3, $4
を足せばよい。awk言語は文字列と数値の区別があいまいである。本来 $2 $3 $4
は入力レコードの部分文字列なので、どれも文字列なのだが、
数字だけの文字列なら足し算をすると数値同士と見なして足し算してくれる。
つまり,$2+$3+$4
と書くだけで3つの数の合計が得られる。
この性質を利用すると、素点のみが記されたCSVに合計点を追加する awk
コマンドラインは以下のようになる。
cat score.csv \
| awk -F, '{printf "%s,%d,%d,%d,%d\n", $1, $2, $3, $4, $2+$3+$4}'
山田太郎,50,70,20,140
公益太郎,90,80,70,240
飯森花子,91,79,72,242
鶴岡一人,60,60,40,160
酒田三吉,52,70,80,202
三川一二三,12,34,99,145
printf
はRubyのものとほとんど同じ書式変換を行なうもので,
上記実行結果が得られる。これでCSVの第5フィールドに合計点が追加された。
あとは、sortコマンドで第5フィールドを数値と見なして並べ替えれば良い。
sortコマンドもデフォルトではフィールド区切りが空白文字なので、
-t ,
としてカンマでフィールド分割させる。
数値と見なして並べ替えるには
-n
オプションを指定する。
cat score.csv \
| awk -F, '{printf "%s,%d,%d,%d,%d\n", $1, $2, $3, $4, $2+$3+$4}' \
| sort -t , -n -k 5
山田太郎,50,70,20,140
三川一二三,12,34,99,145
鶴岡一人,60,60,40,160
酒田三吉,52,70,80,202
公益太郎,90,80,70,240
飯森花子,91,79,72,242
おっとしまった、小さい順(昇順)に並んでしまったので、並べ替えを
逆にする -r
オプションも付けよう。
cat score.csv \
| awk -F, '{printf "%s,%d,%d,%d,%d\n", $1, $2, $3, $4, $2+$3+$4}' \
| sort -r -t , -n -k 5
飯森花子,91,79,72,242
公益太郎,90,80,70,240
酒田三吉,52,70,80,202
鶴岡一人,60,60,40,160
三川一二三,12,34,99,145
山田太郎,50,70,20,140
順位を付けたかったら、行番号を付ける cat -n
に渡す。
cat score.csv \
| awk -F, '{printf "%s,%d,%d,%d,%d\n", $1, $2, $3, $4, $2+$3+$4}' \
| sort -r -t , -n -k 5 \
| cat -n
1 飯森花子,91,79,72,242
2 公益太郎,90,80,70,240
3 酒田三吉,52,70,80,202
4 鶴岡一人,60,60,40,160
5 三川一二三,12,34,99,145
6 山田太郎,50,70,20,140
先頭の空白が多すぎだと思ったら、sedコマンドで文字列の置換(s命令)を使って スペースを4つ削る。
cat score.csv \
| awk -F, '{printf "%s,%d,%d,%d,%d\n", $1, $2, $3, $4, $2+$3+$4}' \
| sort -r -t , -n -k 5 \
| cat -n \
| sed 's/ //' (← s/ の後ろのスペースは4つ)
1 飯森花子,91,79,72,242
2 公益太郎,90,80,70,240
3 酒田三吉,52,70,80,202
4 鶴岡一人,60,60,40,160
5 三川一二三,12,34,99,145
6 山田太郎,50,70,20,140
ついでに、カンマもTAB文字に変えちゃえ。またsedの置換(s命令)を 使ってTAB文字に変換。
cat score.csv \ | awk -F, '{printf "%s,%d,%d,%d,%d\n", $1, $2, $3, $4, $2+$3+$4}' \ | sort -r -t , -n -k 5 \ | cat -n \ | sed 's/ //' \ | sed 's/,/ /g' (← の部分はC-v TABで入力) 1 飯森花子 91 79 72 242 2 公益太郎 90 80 70 240 3 酒田三吉 52 70 80 202 4 鶴岡一人 60 60 40 160 5 三川一二三 12 34 99 145 6 山田太郎 50 70 20 140
プログラム書かなくっても、終わっちゃった、めでたしめでたし。