
Ich verwende Ubuntu 18.04 und die Standard-Coreutils. Mir fällt ein besonderes Verhalten des sort
Befehls auf, dessen Erklärung ich nicht genau weiß.
Betrachten Sie den folgenden Befehl:
$ cat <<EOF | sort
0-
01-
EOF
0-
01-
Diese Ausgabe ist sinnvoll, da -
sie einen kleineren ASCII-Wert hat als 1
und daher diese Ausgabe erwartet wird.
Wenn ich jedoch am Ende noch ein Zeichen einfüge:
$ cat <<EOF | sort
0-T
01-T
EOF
01-T
0-T
Diese Ausgabe ergibt für mich keinen Sinn, da sie meiner Meinung nach 0-T
zuerst kommen sollte. Warum passiert das? Was übersehe ich hier? Habe ich eine falsche Erwartung?
Antwort1
Dies hängt von der Sortierreihenfolge Ihres Gebietsschemas ab.
Bei der Sortierreihenfolge handelt es sich um einen Satz von Regeln für jedes Gebietsschema, der die Reihenfolge der Buchstaben mit Akzent ermöglicht (im Spanischen beispielsweise „ ñ
kommt nach“ n
, aber davor o
).
Aber das ist noch nicht alles, die Sortierreihenfolge gibt auch an, welche Zeichen beim Sortieren ignoriert werden sollen. Für das Gebietsschema „C“ werden alle Zeichen berücksichtigt, für „en_US“ wird beispielsweise der Bindestrich (U002D) ignoriert, wie für die meisten anderen Gebietsschemas auch, da diese die Definitionen von iso14651_t1_common erben (in einigen Distributionen unter /usr/share/i18n/locales/).
Die Reihenfolge Ihrer ersten Datei stellt also kein Problem dar, da Sie, wenn Sie die Bindestriche ignorieren, einen einfachen alphabetischen Vergleich erhalten:
-- ignore dashes --> -- sort -->
0- 0 0
01- 01 01
Wenn Sie das „T“ hinzufügen, ändern sich die Dinge. Warum? Weil Sie jetzt, wenn Sie die Bindestriche ignorieren, „1“ und „T“ vergleichen müssen (das erste Zeichen ist dasselbe) und „1“ vor „T“ steht:
-- ignore dashes --> -- sort -->
0-T 0T 01T
01-T 01T 0T
Daher ist es eine gute Idee, immer sicherzustellen, dass Sie die „C“-Regeln verwenden, indem Sie beim Sortieren LC_COLLATE=C verwenden.
In Ihrem Fall:
$ cat <<EOF | LC_COLLATE=C sort
0-T
01-T
EOF
ergibt:
0-T
01-T
Wie erwartet.
Antwort2
Ja, es kann nervig erscheinen. (in einem Standardgebietsschema von en_US.UTF-8)
$ printf '%s\n' 1 1- 1-a 11- 11-a | sort
1
1-
11-
11-a
1-a
Der Grund hierfür liegt darin, dass die Zuordnung zum Sortierauftrag -
erfolgt .no weight
Ähnlich dem, was ein "
tun sollte:
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
Wie Sie oben sehen können, sind alle 1 zusammen sortiert, alle 11
auch. Das Problem ist, dass 1-a
mehr nacheinander sortiert wird 1a
als nach allem anderen:
printf '%s\n' 1-a 1-b 1-c 1a 1b 1c| sort
1-a
1a
1-b
1b
1-c
1c
ObInterpunktion( -
, "
, ;
und andere) sollten in die Sortierreihenfolge der Sortierung einbezogen werden. Die vorherrschende Meinung ist, dass dies nicht der Fall sein sollte (in Nicht-ASCII-Gebietsschemas).
DergemeinsamDie Datei für die meisten lateinischen Sprachen lautet /usr/share/i18n/locales/iso14651_t1_common
. In dieser Datei ist die HYPHEN-MINUS
Sortierreihenfolge (ja, was wir in Laiensprache Bindestrich nennen. Unicode U-002D) wie folgt festgelegt:
<U002D> IGNORE;IGNORE;IGNORE;<U002D> % HYPHEN-MINUS
Das heißt, ignorieren Sie die ersten drei Sortierebenen.