sortコマンドを使ってヘッダ付きのcsvファイルを指定した列をキーにしてソートする

この記事に書いてあること

csvファイルをコマンドを使って、特定の列を条件にソートする方法をメモしておきます。 ヘッダもソート結果のファイルに移動します。

$ (head -n 1 test.csv && tail -n +2 test.csv | sort -t , -k 3) > test_sort.csv

上のコマンドによって、 test.csvの先頭行をヘッダとして扱って出力先ファイルにもヘッダとして書き出し、 2行目以降からファイル末尾までを区切り文字をカンマとして3列目をキーとしてソートしてファイルに出力します。

コマンドの実行例

以下のようなcsvファイルをソートしたいとします。

name, date, productNumber, count
"Boghos Gayane", 2024-02-11, 95aa0814-c673-4fa6-8c20-a5bce52287d7, 2
"Arsen Nazaret", 2024-01-31, 3b31a0a5-87cb-406a-b657-5f715571b59a, 11
"Boghos Sergo", 2024-01-01, 3d4aa00a-3d2f-44d7-b809-42ea0aeca753, 6
"Celine Dion",  2024-02-01, a4419665-b2e4-4571-b450-23e3adcc2914, 9
"Abel Hurik", 2024-03-01, 6fa7df0f-9e53-4782-8205-0d28d8bc368a, 11
"Boghos Gayane", 2024-02-14, a2aef909-d4bb-4e97-970f-1008666ae1cb, 21
"Abel Hurik", 2024-01-01, 64b6467e-c8d9-431b-8bc7-48f43304a768, 3
"Edvard Gevorg", 2024-01-04, d8ffc526-e803-4e9c-9322-4f2d6999b4c6, 12
"Edvard Marine", 2024-02-06, 2e340fd0-1911-4b11-be35-f8c08f210838, 1
"Dwyane Wade", 2024-01-04, 22e8e2d6-3d78-41fa-8dbc-436e5bb8de9d, 9

冒頭のコマンドを使ってソートをおこなうと、以下のようになったソート済ファイルが取得できます。

name, date, productNumber, count
"Dwyane Wade", 2024-01-04, 22e8e2d6-3d78-41fa-8dbc-436e5bb8de9d, 9
"Edvard Marine", 2024-02-06, 2e340fd0-1911-4b11-be35-f8c08f210838, 1
"Arsen Nazaret", 2024-01-31, 3b31a0a5-87cb-406a-b657-5f715571b59a, 11
"Boghos Sergo", 2024-01-01, 3d4aa00a-3d2f-44d7-b809-42ea0aeca753, 6
"Abel Hurik", 2024-01-01, 64b6467e-c8d9-431b-8bc7-48f43304a768, 3
"Abel Hurik", 2024-03-01, 6fa7df0f-9e53-4782-8205-0d28d8bc368a, 11
"Boghos Gayane", 2024-02-11, 95aa0814-c673-4fa6-8c20-a5bce52287d7, 2
"Boghos Gayane", 2024-02-14, a2aef909-d4bb-4e97-970f-1008666ae1cb, 21
"Celine Dion",  2024-02-01, a4419665-b2e4-4571-b450-23e3adcc2914, 9
"Edvard Gevorg", 2024-01-04, d8ffc526-e803-4e9c-9322-4f2d6999b4c6, 12

コマンドの内容

ここから、コマンドとオプションについて調べたことをメモしておきます。

headコマンド

ファイル先頭から指定された行数だけ読み取るコマンド。

オプション-n--lines)によって読み取る行数を指定しますが、指定がなければ10行になります。 今回は-n 1とすることで先頭1行を読み取っています。

行数にマイナスをつけることで、ファイル末尾からその行数を除いた位置まで読み取ります。 例えば-n -3とすると、ファイル末尾から3行を除いた分を読み取ります。 今回の例では全部で11行あるので、1行目から8行目まで読み取ります。

tailコマンド

ファイル末尾から指定された行数だけ読み取るコマンド。 headの反対です。

オプション-n--lines)によって読み取る行数を指定しますが、指定がなければ10行になります。 行数にプラスをつけることで、ファイル先頭からその行数を除いた位置まで読み取ります。

今回は-n +2とすることで先頭から2行目から末尾までを読み取っています。

sortコマンド

ファイルをソートするコマンド。

オプション-t--field-separator)によって区切り文字を指定します。 今回は-t ,とすることで、カンマを区切り文字にします。

オプション-k--key)によってソートに使うキーの列数を決めます。 今回は-k 3として3列目であるproductNumberをアルファベット順でソートします。

今回は指定していませんが、 オプション-n--numeric-sort)によってアルファベット順ではなく数値としてソートをおこないます。 今回のファイルでは4列目のcountを数値としてソートしたければ、これを使います。

また、オプション-rを使うと逆順(降順)でソートをおこなうことができます。

おまけ(改行コードをsedコマンドで変換する)

sortコマンドを使うときに、改行コードを揃えておきたいときがあります。 Windowsで使われるCRLF(\r\n)からLF(\n)に変換するためにはsedコマンドを使います。

以下のようにすると、ファイルを上書きします。

$ sed -i 's/\r//g' test.csv

参考