¿Por qué la clasificación ignora los caracteres no alfanuméricos?

¿Por qué la clasificación ignora los caracteres no alfanuméricos?

Al ordenar nombres de archivos, lsignora caracteres como -,_. Esperaba que también usara esos caracteres al ordenar.

Un ejemplo:

touch a1 a2 a-1 a-2 a_1 a_2 a.1 a.2 a,1 a,2

Ahora muestre estos archivos con ls -1:

a1
a_1
a-1
a,1
a.1
a2
a_2
a-2
a,2
a.2

Lo que esperaba era algo como esto:

a1
a2
a,1
a,2
a.1
a.2
a_1
a_2
a-1
a-2

es decir, esperaba que se tuvieran en cuenta los caracteres no alfanuméricos al realizar la clasificación.

¿Alguien puede explicar este comportamiento? ¿Este comportamiento está exigido por un estándar? ¿O se debe a que la codificación es UTF-8?

Actualizar:Parece que esto está relacionado con la clasificación UTF-8:

$ LC_COLLATE=C ls -1
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

Respuesta1

EDITAR: prueba agregada para datos ordenados con LC_COLLATE=C


La secuencia de clasificación predeterminada trata esos caracteres de "tipo de puntuación" como si tuvieran el mismo valor... Use LC_COLLATE=Cpara tratarlos en orden de puntos de código...

for i in 'a1' 'a_1' 'a-1' 'a,1' 'a.1' 'a2' 'a_2' 'a-2' 'a,2' 'a.2' ;do
  echo $i; 
done |LC_COLLATE=C sort

Producción

a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

El siguiente código prueba todoválidoCaracteres UTF-8 en el plano multilingüe básico (excepto\x00y\x0a; para simplificar)
Compara un archivo en una secuencia ascendente conocida (generada), con ese archivo ordenado aleatoriamente y luego ordenado nuevamente con LC_COLLATE=C. El resultado muestra que elCLa secuencia es idéntica a la secuencia generada original.

{ i=0 j=0 k=0 l=0
  for i in {0..9} {A..F} ;do
  for j in {0..9} {A..F} ;do
  for k in {0..9} {A..F} ;do
  for l in {0..9} {A..F} ;do
     (( 16#$i$j$k$l == 16#0000 )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l == 16#000A )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l >= 16#D800    && 
        16#$i$j$k$l <= 16#DFFF )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l >= 16#FFFE )) && { printf '.' >&2; continue; }
     echo 0x"$i$j$k$l" |recode UTF-16BE/x4..UTF-8 || { echo "ERROR at codepoint $i$j$k$l " >&2; continue; } 
     echo 
  done
  done
  done; echo -n "$i$j$k$l " >&2
  done; echo >&2
} >listGen

             sort -R listGen    > listRandom
LC_COLLATE=C sort    listRandom > listCsort 

diff <(cat listGen;   echo "last line of listOrig " ) \
     <(cat listCsort; echo "last line of listCsort" )
echo 
cmp listGen listCsort; echo 'cmp $?='$?

Producción:

63485c63485
< last line of listOrig 
---
> last line of listCsort

cmp $?=0

Respuesta2

Esto no tiene nada que ver con el conjunto de caracteres. Más bien, es el idioma el que determina el orden de clasificación. La libc examina el lenguaje presentado en $LC_COLLATE/ $LC_ALL/ $LANGy busca sus reglas de clasificación (por ejemplo, /usr/share/i18n/locales/*para GLibC) y ordena el texto según las instrucciones.

Respuesta3

Tengo exactamente el mismo problema con las opciones de clasificación predeterminadas de Debian, para mí es una coma que ignora y que me impide ordenar los datos CSV de manera efectiva, causando estragos en mi IA.

La solución es, en lugar de usarla sortsola, necesito forzar la ordenación del comportamiento predeterminado que parece ser -d, --dictionary-order.

Ejecutando el comando:

sort -V

Soluciona mi problema y considera comas.

Respuesta4

solo un comentario... tengo un gran problema con mi colación (es_AR.utf8) porque no puedo usar 'C' por los acentos y lo peor de todo es que el problema también aparece en la base de datos postgresql al hacer esa oración entre '10 ' y '10.1' incluyen (es un ejemplo) el valor '100' que no espero... Supongo que tengo que usar la intercalación en cada consulta... SELECCIONE '100' ENTRE '10' Y '10.Z ' muestra verdadero pero SELECCIONAR '100' ENTRE '10' Y '10.Z' COLLATE "C" muestra 'falso', lo cual es correcto (en mi opinión)

información relacionada