Ordem de classificação inesperada na localidade en_US.UTF-8

5

Ao tentar responder a essa pergunta sobre classificação em SQL , notei uma ordem sort que não esperava:

$ 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
$ 

Por que 700 A está classificado acima de 700A , enquanto 700A está acima de 700 W ? Eu esperaria um espaço antes de A consistentemente, independente dos caracteres que o seguem.

Funciona bem se você usar o idioma 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
$ 
    
por Andomar 31.12.2015 / 00:07

1 resposta

7

O truque é que, de certa forma, a classificação é feita em várias etapas. Cada caractere tem três (ou às vezes mais) pesos atribuídos a ele. Digamos que para este exemplo os pesos sejam

space = [0000.0020.0002]
A     = [1BC2.0020.0008]

Criando a chave de ordenação, os pesos diferentes de zero de um string são concatenados, um nível de peso por vez. Então

" A" = 1BC2 0020 0020 0002 0008
"A"  = 1BC2 0020 0008
"A " = 1BC2 0020 0020 0008 0002

Se você classificar esses arrays, receberá o pedido:

1BC2 0020 0008           => "A"
1BC2 0020 0020 0002 0008 => " A"
1BC2 0020 0020 0008 0002 => "A "

Esta é uma simplificação do que realmente acontece; consulte o Algoritmo de agrupamento Unicode para obter mais detalhes. Os pesos de exemplo acima são, na verdade, da tabela padrão, com alguns detalhes omitidos.

    
por 31.12.2015 / 00:47