Dies ist eine Folge davon, dass diese Zeichen die gleiche Sortierreihenfolge haben.
Das werden Sie auch bemerken
sort -u << EOF
■
⅕
⅖
⅗
EOF
gibt nur eine Zeile zurück.
Oder das:
expr ■ = ⅕
Gibt true zurück (wie von POSIX verlangt).
Die meisten mit GNU-Systemen gelieferten Gebietsschemas haben eine Anzahl von Zeichen (und sogar Folgen von Zeichen (Sortierfolgen)), die dieselbe Sortierreihenfolge haben. Bei diesen ist die Reihenfolge nicht definiert, und Zeichen, deren Reihenfolge nicht definiert ist, haben in GNU-Systemen dieselbe Sortierreihenfolge. Es gibt Zeichen, die explizit so definiert sind, dass sie die gleiche Sortierreihenfolge wie Ș und Ş haben (obwohl es (für mich jedenfalls) keine wirkliche Logik oder Konsistenz darüber gibt, wie es gemacht wird).
Das ist die Quelle ziemlich überraschender und falscher Verhaltensweisen. Ich habe das Problem vor kurzem in der Mailingliste der Austin-Gruppe (der Stelle hinter POSIX und der Single UNIX Specification) angesprochen, und die Diskussion ist ab dem 03.04.2015 noch nicht abgeschlossen.
In diesem Fall ist mir unklar , ob wo und nach welcher Sortierung [y]
übereinstimmen soll. Da jedoch ein Klammerausdruck mit einem Sortierelement übereinstimmen soll, lässt dies darauf schließen, dass das Verhalten erwartet wird.x
x
y
bash
In jedem Fall denke ich, [⅕-⅕]
oder [⅕-⅖]
sollte zumindest übereinstimmen ■
.
Sie werden feststellen, dass sich verschiedene Tools unterschiedlich verhalten. ksh93 verhält sich wie bash
GNU grep
oder sed
nicht. Einige andere Muscheln haben ein anderes Verhalten, andere mögen yash
noch buggyiger sein.
Für ein konsistentes Verhalten benötigen Sie ein Gebietsschema, in dem alle Zeichen unterschiedlich sortiert sind. Das Gebietsschema C ist das typische. Bei den meisten Systemen ist der Zeichensatz in der Ländereinstellung C jedoch ASCII. Auf GNU-Systemen haben Sie im Allgemeinen Zugriff auf ein C.UTF-8
Gebietsschema, mit dem Sie stattdessen UTF-8-Zeichen bearbeiten können.
So:
(export LC_ALL=C.UTF-8; [[ ■ = [⅕⅖⅗] ]])
oder das Standardäquivalent:
(export LC_ALL=C.UTF-8
case ■ in ([⅕⅖⅗]) true;; (*) false; esac)
sollte false zurückgeben.
Eine andere Alternative wäre, nur LC_COLLATE
auf C zu setzen , was auf GNU-Systemen funktionieren würde, aber nicht unbedingt auf anderen, bei denen es fehlschlagen könnte, die Sortierreihenfolge von Mehrbyte-Zeichen anzugeben.
Eine Lehre daraus ist, dass Gleichheit keine so klare Vorstellung ist, wie man es beim Vergleichen von Strings erwarten würde. Gleichheit könnte bedeuten, von streng bis am wenigsten streng.
- Die gleiche Anzahl von Bytes und alle Byte-Bestandteile haben den gleichen Wert.
- Die gleiche Anzahl von Zeichen und alle Zeichen sind gleich (beziehen Sie sich beispielsweise auf denselben Codepunkt im aktuellen Zeichensatz).
- Die beiden Zeichenfolgen haben dieselbe Sortierreihenfolge wie der Sortieralgorithmus des Gebietsschemas (d. H., Weder a <b noch b> a ist wahr).
Für 2 oder 3 wird davon ausgegangen, dass beide Zeichenfolgen gültige Zeichen enthalten. In UTF-8 und einigen anderen Codierungen bilden einige Bytefolgen keine gültigen Zeichen.
1 und 2 sind deshalb nicht unbedingt gleichwertig, oder weil einige Zeichen möglicherweise mehr als eine mögliche Kodierung haben. Dies ist in der Regel der Fall bei statusbehafteten Codierungen wie ISO-2022-JP, bei denen A
entweder 41
oder ausgedrückt werden kann 1b 28 42 41
( 1b 28 42
die Reihenfolge, in der auf ASCII umgeschaltet wird, und Sie können so viele davon einfügen, wie Sie möchten, was keinen Unterschied macht), obwohl ich Ich würde nicht erwarten, dass diese Codierungstypen immer noch verwendet werden, und GNU-Tools funktionieren zumindest im Allgemeinen nicht richtig mit ihnen.
Beachten Sie auch, dass die meisten Nicht-GNU-Dienstprogramme den 0-Byte-Wert (das NUL-Zeichen in ASCII) nicht verarbeiten können.
Welche dieser Definitionen verwendet wird, hängt vom Dienstprogramm und der Implementierung oder Version des Dienstprogramms ab. POSIX ist diesbezüglich nicht 100% klar. In der Ländereinstellung C sind alle 3 gleichwertig. Außerhalb dieser YMMV.