回答しようとしたところ、 SQLの並べ替えに関するこの質問 に、予期しないsort
の順序に気づきました。
$ export LC_ALL=en_US.UTF-8
$ echo "T-700A Grouped" > sort.txt
$ echo "T-700 AGrouped" >> sort.txt
$ echo "T-700A Halved" >> sort.txt
$ echo "T-700 Whole" >> sort.txt
$ cat sort.txt | sort
T-700 AGrouped
T-700A Grouped
T-700A Halved
T-700 Whole
$
700 A
が700A
の上にあるのに、700A
が700 W
の上に並べ替えられているのはなぜですか?それに続く文字とは関係なく、A
の前にスペースが一貫して来ることを期待します。
Cロケールを使用すると、正常に機能します。
$ export LC_ALL=C
$ echo "T-700A Grouped" > sort.txt
$ echo "T-700 AGrouped" >> sort.txt
$ echo "T-700A Halved" >> sort.txt
$ echo "T-700 Whole" >> sort.txt
$ cat sort.txt | sort
T-700 AGrouped
T-700 Whole
T-700A Grouped
T-700A Halved
$
トリックは、いわば、ソートが複数のパスで行われるということです。すべての文字には、3つ(場合によってはそれ以上)の重みが割り当てられています。この例では、重みが次のようになっているとしましょう。
space = [0000.0020.0002]
A = [1BC2.0020.0008]
ソートキーを作成すると、文字列の文字のゼロ以外の重みが、一度に1つの重みレベルで連結されます。つまり、重みがゼロの場合、対応する重みは追加されません(" A"
の最初に見られるように)。そう
" A" = 1BC2 0020 0020 0002 0008
"A" = 1BC2 0020 0008
"A " = 1BC2 0020 0020 0008 0002
これらの配列を並べ替えると、次のような順序になります。
1BC2 0020 0008 => "A"
1BC2 0020 0020 0002 0008 => " A"
1BC2 0020 0020 0008 0002 => "A "
これは実際に起こることを単純化したものです。詳細については、 nicode Collation Algorithm を参照してください。上記の例の重みは実際には標準テーブルからのもので、一部の詳細は省略されています。