思った通りに sort されない (LC_COLLATE=en_US.UTF-8 の罠)

Linux

ls -l | sort したら、思った通りの順番に並ばないという相談を受けた。その方のLinux環境では、このように並ぶらしい。

一見して変だ。先頭の文字は通常は - d t の順序(ASCIIコード順)に並ぶのだが、 これは d – t の順にならんでいる。 d t – でもないのが怪しさを増している。

$ ls -l /var/log | sort
drwx------  2 root      root               4096 Jul 12  2021 private
drwxr-sr-x+ 2 root      systemd-journal    4096 Jun  4  2021 journal
drwxr-x---  2 root      adm                4096 Jul 22  2020 unattended-upgrades
drwxr-xr-x  2 landscape landscape          4096 Jul 12  2021 landscape
drwxr-xr-x  2 root      root               4096 May 13 10:01 apt
drwxr-xr-x  2 root      root               4096 May 14  2021 dist-upgrade
drwxr-xr-x  2 root      root               4096 Nov 10  2020 gdm3
-rw-------  1 root      root                  0 Jul 12  2021 ubuntu-advantage.log
-rw-------  1 root      root                  0 Nov  5  2021 ubuntu-advantage-license-check.log
-rw-------  1 root      root                  0 Nov  5  2021 ubuntu-advantage-timer.log
-rw-r--r--  1 root      root            1225679 May 13 10:02 dpkg.log
-rw-r--r--  1 root      root              34006 May 13 09:39 alternatives.log
-rw-r--r--  1 root      root               3835 Apr 25 21:00 fontconfig.log
-rw-r--r--  1 root      root               9851 Jul 14  2021 Xorg.0.log
-rw-r--r--  1 root      root               9851 Jul 14  2021 Xorg.0.log.old
-rw-rw----  1 root      utmp                  0 Jun  4  2021 btmp
-rw-rw-r--  1 root      utmp             292292 Apr 25 20:59 lastlog
-rw-rw-r--  1 root      utmp              50688 Dec 10 01:23 wtmp
total 1644

LC_COLLATEがen_US.UTF-8だと発生する

sortの順序なのだから、LC_COLLATEなのだろうと当たりをつけて調べてみると、私の環境でも LC_COLLATE=en_US.UTF-8 なら奇妙なsortになるようだ。なんだこれ。

よくよく調べてみると、en_USの場合は、辞書式順序で並び替えを行うらしい。 その場合、 ハイフン “-" を抜いた残りで並べ替えるようだ。なるほど確かに、先のsort結果は – を抜いてみると d r t の順に並んでいて正しいようだ。

英語版Wikipediaでも、スペースやハイフンを抜いて並べ替えるのを辞書式順(dictionary order)と呼んでいる。これが GNU sort で採用されている並べ替えの順序なのだろう。

When some of the strings being ordered consist of more than one word, i.e., they contain spaces or other separators such as hyphens, then two basic approaches may be taken. In the first approach, all strings are ordered initially according to their first word, as in the sequence:

Oak; Oak Hill; Oak Ridge; Oakley Park; Oakley River
where all strings beginning with the separate word Oak precede all those beginning Oakley, because Oak precedes Oakley in alphabetical order.
In the second approach, strings are alphabetized as if they had no spaces, giving the sequence:

Oak; Oak Hill; Oakley Park; Oakley River; Oak Ridge
where Oak Ridge now comes after the Oakley strings, as it would if it were written “Oakridge".
The second approach is the one usually taken in dictionaries, and it is thus often called dictionary order by publishers. The first approach has often been used in book indexes, although each publisher traditionally set its own standards for which approach to use therein; there was no ISO standard for book indexes (ISO 999) before 1975.

Alphabetical order – Wikipedia(強調は私による)



ちなみに、arch LinuxのWikiのロケールの項目には「潜在的な問題を回避するため、Arch では以前 /etc/profile で LC_COLLATE=C と設定していましたが、現在は使われなくなっています」と書かれている。


locale奥が深すぎる…


リンク

Linux

Posted by ず@沖縄