警告
コメントを受けてGhostBSD(FreeBSD)で確認してみたのですが、GhostBSDでは回避策に書いてあるようなことをしなくても問題なく動作しました。なので、かなり限られた環境での問題である可能性が高いです1。ただ、私の手元(の一部、具体的には新しいMac)で問題が起きているのは事実ですので、記事としては残しておきます。
はじめに
皆さん、ファイルの行を並べ替えるために普段からsortをお使いのことと思います。そこで出会った不可解な現象とその回避策について書きます。
また、恒例のお断りですが、この文章の内容は、筆者が所属している会社・団体とは一切関わりがありません。いわゆる「自主的な研究の成果の発表」というものです。
さて困った
sortで英数字の内容のファイルを並べ替えている分にはびっくりすることは起こりません。が、日本語が入ったファイルを相手にすると途端に謎な動作になります。この動作はGNU版(Linuxなら多分こちら)でもBSD版(macOSとかGhostBSD/FreeBSDとか)でも変わりません。例を示します。
以下のようなファイルtest.txtがあるとします。(もちろんファイル名はどうでもいいのですが。)
c
aaaaa
bbb
ええ
あああ
いい
う
い
あ
これを並べ替えると当然「abc順、あいうえお順に並ぶ」と思いますよね。で、実際にやってみました。
$ sort test.txt
aaaaa
bbb
c
あ
い
う
いい
ええ
あああ
「a、b、c」、うんうん、あってる、あってる。「あ、い、う」、ん?「い、え、あ」ええ???
英語はおかしくないのですが、日本語になると、
- まず文字数の順に整列
- 同じ文字数の中であいうえお順
みたいな動作をしているようです。これはこれで役に立つ場合もあるのですが、普通は文字数に関係なくあいうえお順に並ぶことを期待するのではないでしょうか。
回避策
ロケールの設定が影響しているようです。なので以下のようにしましょう。
$ LC_COLLATE=C sort test.txt
aaaaa
bbb
c
あ
あああ
い
いい
う
ええ
はい、これで期待した通りに動作しました。
説明は不要かもしれませんが、sortの前の"LC_COLLATE=C"というのは「このsortの時だけ環境変数のLC_COLLATEの値をCにせよ」ということです。ですので、既存の環境には影響を与えません2。
また、LC_COLLATEの代わりにLC_ALLやLANGも使えます。
ちなみに私の環境ではLANG=ja_JP.UTF-8となっていたのが良くなかったようです。(と言われても、この環境変数を変更するとどこまで影響するか怖くて、そんなことはできません。)
-
そういえば古いMacでも似たようなことをやったことがあるのですが、その時はこんな問題に悩まされることはありませんでした。 ↩
-
ナウいMacにとってもナウいPostgreSQLをインストールするでも使った方法です。だから「(無駄な努力な気がしますが)既存の環境にはできるだけ影響を与えないようにしています。」と書きました。 ↩