Collation um durch LC_COLLATE
definiert nicht nur die Sortierreihenfolge der einzelnen Zeichen, sondern auch die Bedeutung des Zeichenbereiches. Oder doch? Betrachten Sie das folgende Snippet:
unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'
Intuitiv B
ist nicht in [a-z]
, daher sollte dies nichts ausgeben. Genau das passiert unter Ubuntu 8.04 oder 10.04. Aber auf einigen Computern, auf denen Debian Lenny oder Squeeze ausgeführt wird, B
wird gefunden, dass der Bereich a-z
alles zwischen a
und z
in der Sortierreihenfolge enthält, einschließlich der Großbuchstaben B
bis Z
.
Bei allen getesteten Systemen wird das en_US
Gebietsschema generiert. Ich habe auch versucht, das Gebietsschema zu ändern: Auf den Computern, auf denen B
die oben angegebenen Übereinstimmungen vorliegen, geschieht dasselbe in jedem verfügbaren Gebietsschema (meistens lateinisch: {en_{AU,CA,GB,IE,US},fr_FR,it_IT,es_ES,de_DE}{iso8859-1,iso8859-15,utf-8}
auch chinesisch) mit Ausnahme von Japanisch (in allen verfügbaren Codierungen) und C
/ POSIX
.
Was bedeuten Zeichenbereiche in regulären Ausdrücken , wenn Sie über ASCII hinausgehen? Warum gibt es einen Unterschied zwischen einigen Debian-Installationen einerseits und anderen Debian-Installationen und Ubuntu andererseits? Wie verhalten sich andere Systeme? Wer hat Recht und gegen wen sollte ein Fehler gemeldet werden?
(Beachten Sie, dass ich speziell nach dem Verhalten von Zeichenbereichen frage, z. B. [a-z]
in en_US
Gebietsschemas, hauptsächlich auf GNU libc-basierten Systemen. Ich frage nicht, wie Kleinbuchstaben oder ASCII-Kleinbuchstaben verglichen werden sollen.)
Auf zwei Debian - Maschinen, ein , wo B
in ist [a-z]
und eine , wo dies nicht der Fall, wird der Ausgang des LC_COLLATE=en_US locale -k LC_COLLATE
IS
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=1
collate-codeset="ISO-8859-1"
und die Ausgabe von LC_COLLATE=en_US.utf8 locale -k LC_COLLATE
ist
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"
quelle
en_US
generiert wurde.C
Gebietsschema als Fallback verwendet, und seine Sortierreihenfolge besteht aus geraden Bytewerten, sodassB
keine Übereinstimmung erzielt wird. Testen Sie in einem Gebietsschema, das in der Ausgabe von angezeigt wirdlocale -a
.Antworten:
Wenn Sie etwas anderes als das
C
Gebietsschema verwenden, sollten Sie keine Bereiche wie[a-z]
diesen verwenden, da diese vom Gebietsschema abhängen und nicht immer die erwarteten Ergebnisse liefern. Neben dem bereits aufgetretenen Fallproblem behandeln einige Gebietsschemas Zeichen mit diakritischen Zeichen (z. B. á ) wie das Basiszeichen (z. B. a ).Verwenden Sie stattdessen eine benannte Zeichenklasse:
Dies gibt immer das richtige Ergebnis für das Gebietsschema. Sie müssen jedoch das Gebietsschema auswählen, das die Bedeutung Ihres Eingabetexts und des Tests, den Sie anwenden möchten, widerspiegelt.
Wenn Sie beispielsweise einen bestimmten Bytewert suchen müssen, verwenden Sie das
C
Gebietsschema, das immer verfügbar ist:Wenn dies nicht wie erwartet funktioniert, ist es wirklich ein Fehler.
quelle
locale -k
zu meiner Frage hinzugefügt . Es ist auf zwei Debian-Maschinen identisch, eine, woB
es im Bereich ist und eine, wo es nicht ist. Übrigens bin ich auf beiden Rechnern nicht root (es ist also nichts Besonderes, was ich als Administrator mache).echo "Baü" | LC_COLLATE=C grep -o '[[:lower:]]'
gibta
UND zurück,ü
währendecho "Baü" | LC_COLLATE=C grep -o '[a-z]'
nur zurückgibta
. In meinen Augen ist "niedriger" nicht wirklich das, was der OP wollteC
Gebietsschema. Ich glaube, dies ist relevant für das OP, das einen Fehler melden wollte. Wenn Sie sich nicht in derC
Ländereinstellung befinden, sind die Ergebnisse der Verwendung von Bereichen sehr unvorhersehbar und können daher niemals als Fehler angesehen werden. Wenn Sie andererseits einen bestimmten Bytewert suchen müssen, verwenden Sie einfach dasC
Gebietsschema. Wenn Sie in einem Gebietsschema wirklich nach Kleinbuchstaben suchen möchten, verwenden Sie eine Zeichenklasse. Auch wenn das OP nicht danach gesucht hat, könnten andere dies tun, wenn sie diese Frage finden.Bereiche in regulären Ausdrücken sollten die Sortierungseinstellung beachten. Hier ist der relevante Standard: http://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html (suchen Sie nach "Bereichsausdrücken"). So
echo B | LC_COLLATE=en_US grep '[a-z]'
sollteB
eine sinnvolle Definition des jeweiligen Gebietsschemas ausgegeben werden . Ich kann nicht erklären, warum dies manchmal bei Ihnen nicht funktioniert, aber ich wäre sehr überrascht, wenn ich dies auf einem nicht alten System antreffen würde, das ordnungsgemäß installiert und konfiguriert ist.quelle
echo B | LC_COLLATE=en_US.utf8 grep '[a-z]'
Gibt unter Ubuntu 12.04 mit grep 2.10 nichts aus. Druckt unter Centos 6.5 mit grep 2.6.3 nichts. Funktioniert auf Debian 6.0.8 mit grep 2.6.3.