Os algoritmos de ordenação nos locais modernos são bastante complexos.
Cada caractere (na verdade, elemento de agrupamento que pode consistir em uma sequência de vários caracteres como o tcheco ch
) recebe um número de pesos de agrupamento que decidem ordem de classificação.
Ao comparar duas strings, o primeiro peso de todos os caracteres é usado primeiro, e outros pesos são usados posteriormente para decidir os laços se as duas strings forem ordenadas da mesma forma com os primeiros pesos.
Por exemplo, em muitos locais, e
, é
e E
têm o mesmo peso primário (eles são da mesma classe de equivalência, todos correspondem a [=e=]
).
Portanto, ao comparar, por exemplo, echo
, été
e Enter
, na primeira passagem, e
, é
e E
tendo o mesmo peso primário, é o segundo caractere que determinará o pedido ( c
antes de n
antes de t
).
Ao comparar été
, Été
, Ete
, após a primeira passagem, todos eles são classificados da mesma forma, então usamos a segunda passagem usando o peso secundário. Em locais típicos do GNU, o segundo peso para caracteres de escrita latina é usado para priorizar os acentos (nenhum acento aparece primeiro, depois agudo, grave, breve, circunflexo ...). Em seguida, precisaremos usar o terceiro peso para decidir entre été
e Été
e isso será baseado no caso (minúsculas primeiro na maioria dos locais). Existem até personagens que acabam classificando o mesmo porque todos os seus pesos são idênticos.
Isso é usado para classificar o texto de maneira similar aos dicionários, como um humano faria.
Em um dicionário, você descobrirá que o espaço e a maioria dos caracteres de pontuação também são ignorados. Por exemplo, de facto
classifica entre debut
e devoid
. O primeiro peso do caractere de espaço é IGNORE.
Em um sistema GNU, você encontrará as regras de intercalação principais definidas no /usr/share/i18n/locales/iso14651_t1_common
(o caminho pode variar com a distribuição). Lá você verá:
ifdef UPPERCASE_FIRST
<CAP>
else
<MIN>
endif
[...]
ifdef UPPERCASE_FIRST
[...]
<MIN> # 10
[...]
else
[...]
<CAP> # 9
[...]
endif
[...]
order_start <SPECIAL>;forward;backward;forward;forward,position
<U0020> IGNORE;IGNORE;IGNORE;<U0020> # 32 <SP>
[...]
<U003E> IGNORE;IGNORE;IGNORE;<h> # 140 >
[...]
ifdef DIACRIT_FORWARD
order_start <LATIN>;forward;forward;forward;forward,position
else
order_start <LATIN>;forward;backward;forward;forward,position
endif
[...]
<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U00E9> <e>;<ACA>;<MIN>;IGNORE # 260 é
[...]
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E
<U00C9> <e>;<ACA>;<CAP>;IGNORE # 578 É
Que ilustram o que acabamos de dizer. O espaço e >
têm seus primeiros 3 pesos definidos como IGNORE
. É apenas para as strings classificarem as mesmas para as 3 primeiras ponderações que sua ordem relativa será considerada ( >
antes do espaço, conforme a <h>
listaria antes do símbolo de classificação não especificado <U0020>
).
Nas localidades que definem UPPERCASE_FIRST
(como /usr/share/i18n/locales/tr_TR
), as letras maiúsculas virão primeiro (na passagem 3 rd ). Mesmo com DIACRIT_FORWARD
, onde algumas localidades como de_DE
podem decidir reverter a ordem dos diacríticos para a passagem de 2 nd .
>
e >>
ordenam o mesmo na passagem 1 st , 2 nd e 3 rd . No 4 th , >
ordena antes de >>
à medida que a string vazia é classificada antes de tudo.
>>b
classifica após b
porque eles ordenam o mesmo nas primeiras 3 passagens, mas na quarta passagem, b
é IGNORE, então >
é maior. É menor que c
na primeira passagem ( >
ignorado e b
antes c
) ... Você entendeu.
Agora, se você observar a definição C
locale. É muito mais simples. Há apenas um peso, e o peso é baseado no valor do ponto no código de U + 0000 para U + 10FFFF. Portanto, SPC
(U + 0020) classifica antes de >
(U + 003E), que classifica antes de b
(U + 0062) que classifica antes de c
(U + 0063). Nenhum personagem é ignorado.
Note que com o GNU libc, pelo menos, essa ordem definida no arquivo de definição de código de idioma C é ignorada quando se trata de funções de comparação ( strcoll()
e co. como usado por sort
). Independentemente do valor de LC_CTYPE
, com LC_COLLATE=C
, strcoll()
é equivalente a strcmp()
. Como na comparação está sempre no valor de byte, mesmo que esses bytes correspondam a caracteres cujo ponto de código unicode faça o contrário (como 0xA4 U + 20AC EURO SIGN vs A5 U + 00A5 YEN SIGN no conjunto de caracteres ISO-8859-15) , então LC_ALL=C sort
e LC_COLLATE=C sort
(desde que LC_ALL
não esteja definido de outra forma) terão o mesmo efeito lá.