Warum ignoriert die LS-Sortierung nicht-alphanumerische Zeichen?

Warum ignoriert die LS-Sortierung nicht-alphanumerische Zeichen?

Beim Sortieren von Dateinamen lswerden 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=Cum 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 sortes 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

verwandte Informationen