TL;DR
Linuxの(GNU)sortを使って3文字の月名でソートしようとしてハマったのでメモ。
環境
$ cat /etc/system-release
CentOS release 6.9 (Final)
$ sort --version | head -1
sort (GNU coreutils) 8.4
お題1
こういうファイルがあるとします。
$ cat a
Dec
Jan
Jul
Sep
Mar
Oct
単純にソートしたら、当然アルファベット順に並びます。
$ sort a
Dec
Jan
Jul
Mar
Oct
Sep
sort コマンドには、キーを月名とみなす -M オプションがあります。
これを使うと、米国表記の月の順にソート
$ sort -M a
Dec
Jan
Jul
Mar
Oct
Sep
されません(汗
マニュアルをじっくり読むと、LC_* 系の環境変数に影響されるっぽいので
$ env|grep LANG
LANG=ja_JP.UTF-8
$ LANG=C sort -M a
Jan
Mar
Jul
Sep
Oct
Dec
明示的に LANG=C したら、今度はうまくいきました。
( -s(--stable) オプションというのもちょっと謎、、、)
お題2
本当にやりたかったのこちら。
こういうファイルがあって、これを日付順にソートしたい。
$ cat b
www.example.com 192.168.0.12 - - [10/May/2017:03:40:22 +0900] snip...
www.example.com 192.168.0.22 - - [10/Sep/2016:03:33:22 +0900] snip...
hoge.example.jp 192.168.0.21 - - [10/May/2017:03:40:22 +0900] snip...
www.example.com 192.168.9.10 - - [15/Sep/2016:03:34:34 +0900] snip...
www.example.com 10.89.159.137 - - [10/Mar/2016:03:35:48 +0900] snip...
www.example.jp 192.168.0.2 - - [10/Sep/2015:03:36:52 +0900] snip...
test.example.com 192.168.0.1 - - [10/Oct/2016:03:37:52 +0900] snip...
www.example.co.jp 10.2.66.247 - - [10/Apr/2017:03:38:20 +0900] snip...
www.example.com 192.168.0.232 - - [10/Apr/2017:03:39:22 +0900] snip...
試行錯誤の結果、以下のようにしたら無事にソートされました。
$ LANG=C sort -t '[' -k2.8,2.11 -k2.4,2.6M -k2.1,2.2 b
www.example.jp 192.168.0.2 - - [10/Sep/2015:03:36:52 +0900] snip...
www.example.com 10.89.159.137 - - [10/Mar/2016:03:35:48 +0900] snip...
www.example.com 192.168.0.22 - - [10/Sep/2016:03:33:22 +0900] snip...
www.example.com 192.168.9.10 - - [15/Sep/2016:03:34:34 +0900] snip...
test.example.com 192.168.0.1 - - [10/Oct/2016:03:37:52 +0900] snip...
www.example.co.jp 10.2.66.247 - - [10/Apr/2017:03:38:20 +0900] snip...
www.example.com 192.168.0.232 - - [10/Apr/2017:03:39:22 +0900] snip...
hoge.example.jp 192.168.0.21 - - [10/May/2017:03:40:22 +0900] snip...
www.example.com 192.168.0.12 - - [10/May/2017:03:40:22 +0900] snip...
オプションは以下のような感じです。
- -t フィールド区切り文字(デフォルトは空白)
- -k キーの指定(後述)
- M :そのキーを月名とみなす
愚痴
"man sort" でぐぐると、
Section: User Commands (1) - sort - テキストファイルをソートする
というありがたい日本語の man ページが読めるんですが、ここの
-k POS1[,POS2]
-K POS1[,POS2] ソートフィールド指定の POSIX 形式。今後はこちらが推奨される。
行の POS1 から POS2 までのフィールドを指定する。 POS2 を含む。
POS2 が省略されたら行末まで。 フィールドと文字位置はそれぞれ 0 から数えはじめる。
この最後の部分が間違っているようです(仕様が変わった?)。
コマンドのヘルプによると、
$ sort --help | sed -n 35,36p
-k, --key=POS1[,POS2] start a key at POS1 (origin 1), end it at POS2
(default end of line)
位置は 1 オリジンらしいです。これに地味にハマりましたw