Beim Sortieren von Dateinamen ls
werden Zeichen wie ignoriert -,_
. Ich hatte erwartet, dass diese Zeichen auch beim Sortieren verwendet werden.
Ein Beispiel:
touch a1 a2 a-1 a-2 a_1 a_2 a.1 a.2 a,1 a,2
Zeigen Sie diese Dateien nun an mit ls -1
:
a1
a_1
a-1
a,1
a.1
a2
a_2
a-2
a,2
a.2
Ich hatte ungefähr Folgendes erwartet:
a1
a2
a,1
a,2
a.1
a.2
a_1
a_2
a-1
a-2
d. h. ich habe erwartet, dass die nicht alphanumerischen Zeichen beim Sortieren berücksichtigt werden.
Kann jemand dieses Verhalten erklären? Ist dieses Verhalten durch einen Standard vorgeschrieben? Oder liegt es daran, dass die Kodierung UTF-8 ist?
Aktualisieren:Dies scheint mit der UTF-8-Sortierung zusammenzuhängen:
$ LC_COLLATE=C ls -1
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2
Antwort1
BEARBEITEN: Test für mit LC_COLLATE=C sortierte Daten hinzugefügt
Die standardmäßige Sortierreihenfolge behandelt diese Zeichen vom „Satzzeichentyp“ als gleichwertig, Use LC_COLLATE=C
um sie in der Codepunktreihenfolge zu behandeln.
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
Ausgabe
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2
Der folgende Code testet allegültigUTF-8-Zeichen in der Basic Multilingual Plane (außer\x00Und\x0a; der Einfachheit halber)
Es vergleicht eine Datei in einer bekannten (generierten) aufsteigenden Reihenfolge mit dieser Datei, die zufällig sortiert und dann erneut mit LC_COLLATE=C sortiert wurde. Das Ergebnis zeigt, dass dieCSequenz ist mit der ursprünglich generierten Sequenz identisch.
{ 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 $?='$?
Ausgabe:
63485c63485
< last line of listOrig
---
> last line of listCsort
cmp $?=0
Antwort2
Dies hat nichts mit dem Zeichensatz zu tun. Vielmehr bestimmt die Sprache die Sortierreihenfolge. Die libc untersucht die in $LC_COLLATE
/ $LC_ALL
/ dargestellte Sprache $LANG
, sucht deren Sortierregeln (z. B. /usr/share/i18n/locales/*
für GLibC) und sortiert den Text wie angegeben.
Antwort3
Ich habe genau das gleiche Problem mit den Standardsortieroptionen von Debian. Bei mir wird ein Komma ignoriert, was mich daran hindert, CSV-Daten zu sortieren, was in meiner KI Chaos anrichtet.
Die Lösung besteht darin, dass ich, anstatt sort
es allein zu verwenden, das Standardverhalten, das zu sein scheint, zwangsweise ändern muss -d, --dictionary-order
.
Ausführen des Befehls:
sort -V
Behebt mein Problem und berücksichtigt Kommas.
Antwort4
nur ein Kommentar... ich habe ein großes Problem mit meiner Sortierung (es_AR.utf8), weil ich 'C' wegen der Akzente nicht verwenden kann und das Schlimmste ist, dass das Problem auch in der PostgreSQL-Datenbank auftritt, da der Satz zwischen '10' und '10.1' (es ist ein Beispiel) den Wert '100' enthält, was ich nicht erwarte... ich schätze, ich muss die Sortierung in jeder Abfrage verwenden... SELECT '100' BETWEEN '10' AND '10.Z' zeigt „true“, aber SELECT '100' BETWEEN '10' AND '10.Z' COLLATE „C“ zeigt „false“, was (meiner Meinung nach) richtig ist