Al ordenar nombres de archivos, ls
ignora 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=C
para 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
/ $LANG
y 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 sort
sola, 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)