
Estoy usando Ubuntu 18.04 y los coreutils predeterminados. Noto un comportamiento particular del sort
comando que no estoy seguro de cómo explicar.
Considere el siguiente comando:
$ cat <<EOF | sort
0-
01-
EOF
0-
01-
Esta salida tiene sentido porque -
tiene un valor ASCII más pequeño 1
y, por lo tanto, se espera esta salida.
Sin embargo, si pongo un personaje más al final:
$ cat <<EOF | sort
0-T
01-T
EOF
01-T
0-T
Este resultado no tiene ningún sentido para mí porque creo que 0-T
debería ser lo primero. Por qué está pasando esto. ¿Que me estoy perdiendo aqui? ¿Tengo una expectativa equivocada?
Respuesta1
Depende del orden de clasificación de su localidad.
El orden de clasificación es un conjunto de reglas para cada ubicación que permiten ordenar letras acentuadas (por ejemplo, ñ
vendrá después n
pero antes o
en español).
Pero eso no es todo, el orden de clasificación también indica qué caracteres deben ignorarse al ordenar. Para la configuración regional "C", se tienen en cuenta todos los caracteres, pero para "en_US", por ejemplo, se ignora el guión (U002D), como ocurre con la mayoría de las demás configuraciones regionales, ya que heredan las definiciones de iso14651_t1_common (en /usr/share/ i18n/locales/ en algunas distribuciones).
Así, el orden de tu primer archivo no supone ningún problema, ya que cuando ignoras los guiones acabas con una simple comparación alfabética:
-- ignore dashes --> -- sort -->
0- 0 0
01- 01 01
Cuando agregas la "T", la cosa cambia, ¿por qué? Porque ahora, si ignoras los guiones tienes que comparar "1" y "T" (el primer carácter es el mismo) y "1" viene antes de "T":
-- ignore dashes --> -- sort -->
0-T 0T 01T
01-T 01T 0T
Por lo tanto, es una buena idea asegurarse siempre de utilizar las reglas de "C", utilizando LC_COLLATE=C al ordenar.
En tu caso:
$ cat <<EOF | LC_COLLATE=C sort
0-T
01-T
EOF
rendimientos:
0-T
01-T
Como esperabas.
Respuesta2
Sí, puede parecer molesto. (en una configuración regional predeterminada de en_US.UTF-8)
$ printf '%s\n' 1 1- 1-a 11- 11-a | sort
1
1-
11-
11-a
1-a
El motivo es que -
está asignado no weight
al orden de clasificación.
Similar a lo que "
debería hacer:
printf '%s\n' 1 \"1\" 1- \"1-\" 1-a \"1-a\" 11- \"11-\" 11-a \"11-a\" | sort
"1"
"1-"
1
1-
"11-"
11-
"11-a"
11-a
"1-a"
1-a
Como puede ver arriba, los 1 están ordenados juntos, todos 11
también. El problema es que 1-a
está ordenado más 1a
que otra cosa:
printf '%s\n' 1-a 1-b 1-c 1a 1b 1c| sort
1-a
1a
1-b
1b
1-c
1c
Sipuntuación( -
, "
, ;
y otros) deben incluirse en el orden de clasificación es controvertido. La opinión predominante ha sido que no debería (en configuraciones regionales que no sean ASCII).
ElcomúnEl archivo para la mayoría de los idiomas latinos es /usr/share/i18n/locales/iso14651_t1_common
. En ese archivo, el HYPHEN-MINUS
orden de clasificación (sí, lo que nosotros, en términos simples, llamamos guión. Unicode U-002D) se establece en:
<U002D> IGNORE;IGNORE;IGNORE;<U002D> % HYPHEN-MINUS
Es decir, ignore los primeros tres niveles de cotejo.