Was macht der C
Wert für LC_ALL
in Unix-ähnlichen Systemen?
Ich weiß, dass es das gleiche Gebietsschema für alle Aspekte erzwingt, aber was macht C
das?
environment-variables
locale
jcubic
quelle
quelle
xclock
warning (Missing charsets in String to FontSet conversion
) lösen möchten , ist es besserLC_ALL=C.UTF-8
, Probleme mit kyrillischer Sprache zu vermeiden. Um diese Umgebungsvariable festzulegen, müssen Sie die folgende Zeile am Ende der~/.bashrc
Datei hinzufügen -export LC_ALL=C.UTF-8
Antworten:
Es erzwingt, dass Anwendungen die Standardsprache für die Ausgabe verwenden:
und zwingt die Sortierung, byteweise zu sein:
quelle
LC_ALL
ist die Umgebungsvariable, die alle anderen Lokalisierungseinstellungen überschreibt ( außer$LANGUAGE
unter bestimmten Umständen ).Verschiedene Aspekte von Lokalisierungen (z. B. Tausendertrennzeichen oder Dezimalzeichen, Zeichensatz, Sortierreihenfolge, Monat, Tagesnamen, Sprach- oder Anwendungsnachrichten wie Fehlermeldungen, Währungssymbol) können mithilfe weniger Umgebungsvariablen festgelegt werden.
In der Regel legen Sie
$LANG
Ihre Präferenz mit einem Wert fest, der Ihre Region kennzeichnet (z. B.fr_CH.UTF-8
wenn Sie sich in der französischsprachigen Schweiz befinden und UTF-8 verwenden). Die einzelnenLC_xxx
Variablen überschreiben einen bestimmten Aspekt.LC_ALL
überschreibt sie alle. Derlocale
Befehl, wenn ohne Argument aufgerufen gibt einen Überblick über die aktuellen Einstellungen.Zum Beispiel bekomme ich auf einem GNU-System:
Ich kann eine individuelle Einstellung überschreiben, zum Beispiel mit:
Oder:
Oder alles mit LC_ALL überschreiben.
Wenn Sie in einem Skript eine bestimmte Einstellung erzwingen möchten, da Sie nicht wissen, welche Einstellungen der Benutzer erzwungen hat (möglicherweise auch LC_ALL), ist die beste, sicherste und allgemein einzige Option, LC_ALL zu erzwingen.
Das
C
Gebietsschema ist ein spezielles Gebietsschema, das das einfachste Gebietsschema sein soll. Man könnte auch sagen, dass die anderen Ländereinstellungen für Menschen sind, die Ländereinstellung C jedoch für Computer. Im Gebietsschema C sind Zeichen Einzelbytes, der Zeichensatz ist ASCII (nun ja, dies ist nicht erforderlich, wird aber in der Praxis in den Systemen verwendet, die die meisten von uns jemals verwenden werden). Die Sortierreihenfolge basiert auf den Bytewerten. Die Sprache ist in der Regel US-Englisch (bei Anwendungsnachrichten (im Gegensatz zu Monats- oder Tagesnamen oder Nachrichten von Systembibliotheken) liegt es im Ermessen des Anwendungsautors) und Währungssymbole sind nicht definiert.Auf einigen Systemen gibt es einen Unterschied zum POSIX-Gebietsschema, bei dem beispielsweise die Sortierreihenfolge für Nicht-ASCII-Zeichen nicht definiert ist.
Im Allgemeinen führen Sie einen Befehl mit LC_ALL = C aus, um zu vermeiden, dass die Einstellungen des Benutzers Ihr Skript beeinträchtigen. Wenn Sie beispielsweise
[a-z]
die 26 ASCII-Zeichen vona
bis abgleichen möchtenz
, müssen Sie festlegenLC_ALL=C
.Auf GNU-Systemen
LC_ALL=C
undLC_ALL=POSIX
(oderLC_MESSAGES=C|POSIX
) außer Kraft setzen$LANGUAGE
, währendLC_ALL=anything-else
nicht.Einige Fälle, in denen Sie normalerweise festlegen müssen
LC_ALL=C
:sort -u
odersort ... | uniq...
. In vielen anderen Gebietsschemas als C haben auf einigen Systemen (insbesondere GNU-Systemen) einige Zeichen dieselbe Sortierreihenfolge .sort -u
meldet keine eindeutigen Zeilen, sondern eine aus jeder Gruppe von Zeilen mit gleicher Sortierreihenfolge. Wenn Sie also eindeutige Zeilen wünschen, benötigen Sie ein Gebietsschema, bei dem die Zeichen Byte sind und alle Zeichen eine unterschiedliche Sortierreihenfolge haben (was dasC
Gebietsschema garantiert).=
Betreiber von POSIX-konformenexpr
oder den==
Betreiber von POSIX-konformenawk
(mawk
undgawk
diesbezüglich nicht POSIX-konformen ) Zeichenketten, die nicht prüfen, ob zwei Zeichenketten identisch sind, sondern ob sie gleich sortieren.grep
. Wenn Sie einen Buchstaben in der Sprache des Benutzers suchen möchten, verwenden Siegrep '[[:alpha:]]'
und ändern Sie ihn nichtLC_ALL
. Wenn Sie jedoch diea-zA-Z
ASCII-Zeichen abgleichen möchten , benötigen Sie entwederLC_ALL=C grep '[[:alpha:]]'
oderLC_ALL=C grep '[a-zA-Z]'
¹.[a-z]
stimmt mit den Zeichen überein, die nacha
und vor sortiert werdenz
(obwohl es bei vielen APIs komplizierter ist). In anderen Regionen wissen Sie im Allgemeinen nicht, was das ist. Beispielsweise ignorieren einige Gebietsschemas die Groß- und Kleinschreibung für die Sortierung, so dass[a-z]
in einigen APIs wiebash
Mustern[B-Z]
oder enthalten sein können[A-Y]
. In vielen UTF-8-Sprachumgebungen (einschließlich deren_US.UTF-8
meisten Systeme)[a-z]
werden die lateinischen Buchstaben vona
bisy
mit diakritischen Zeichen eingeschlossen, nicht jedoch die vonz
(seit)z
Ich kann mir nicht vorstellen, was Sie wollen (warum sollten Sie einbeziehené
und nichtź
?).Gleitkomma-Arithmetik in
ksh93
.ksh93
ehrt diedecimal_point
Einstellung inLC_NUMERIC
. Wenn Sie ein Skript schreiben, das Folgendes enthälta=$((1.2/7))
, funktioniert es nicht mehr, wenn es von einem Benutzer ausgeführt wird, dessen Gebietsschema Komma als Dezimaltrennzeichen hat:Dann brauchen Sie Dinge wie:
Als Randnotiz: Das
,
Dezimaltrennzeichen steht in Konflikt mit dem,
arithmetischen Operator, was noch mehr Verwirrung stiften kann.grep '<.*>'
nach Zeilen suchen, die ein enthalten<
,>
funktioniert pair nicht, wenn Sie sich in einem UTF-8-Gebietsschema befinden und die Eingabe in einem Einzelbyte-8-Bit-Zeichensatz wie iso8859-15 codiert ist..
Dies liegt daran, dass nur Übereinstimmungen und Nicht-ASCII-Zeichen in ISO8859-15 wahrscheinlich kein gültiges Zeichen in UTF-8 bilden. Funktioniert jedoch,LC_ALL=C grep '<.*>'
da jeder Byte-Wert imC
Gebietsschema ein gültiges Zeichen bildet .Jedes Mal, wenn Sie Eingabedaten oder Ausgabedaten verarbeiten, die nicht für einen Menschen bestimmt sind. Wenn Sie mit einem Benutzer sprechen, möchten Sie möglicherweise dessen Konvention und Sprache verwenden. Wenn Sie jedoch beispielsweise Zahlen generieren, um eine andere Anwendung zu unterstützen, die englische Dezimalstellen oder englische Monatsnamen erwartet, möchten Sie dies setze LC_ALL = C:
Das gilt auch für Dinge wie case insensitive compare (wie in
grep -i
) und case conversion (awk
'stoupper()
,dd conv=ucase
...). Zum Beispiel:Es wird nicht garantiert, dass die Übereinstimmung
I
im Gebietsschema des Benutzers vorliegt. In einigen türkischen Gegenden zum Beispiel tut es nicht als Großbuchstabei
istİ
( man beachte den Punkt) gibt und KleinI
istı
( man beachte den fehlenden Punkt).¹ Abhängig von der Kodierung des Textes ist dies jedoch nicht unbedingt das Richtige. Dies gilt für UTF-8- oder Einzelbyte-Zeichensätze (wie iso-8859-1), jedoch nicht unbedingt für Nicht-UTF-8-Multibyte-Zeichensätze.
Wenn Sie sich beispielsweise in einem
zh_HK.big5hkscs
Gebietsschema befinden (Hongkong mit der Hongkong-Variante der chinesischen BIG5-Zeichencodierung) und in einer in diesen Zeichensätzen codierten Datei nach englischen Buchstaben suchen möchten, gehen Sie folgendermaßen vor:oder
wäre falsch, da in diesem Zeichensatz (und vielen anderen, die seit dem Erscheinen von UTF-8 kaum mehr verwendet wurden) viele Zeichen Bytes enthalten , die der ASCII-Codierung von A-Za-Z-Zeichen entsprechen. Beispielsweise enthalten alle
A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽
(und viele weitere) die Codierung vonA
.䨝
ist 0x96 0x41 undA
ist 0x41 wie in ASCII. AlsoLC_ALL=C grep '[a-zA-Z]'
würden wir in den Zeilen, die diese Zeichen enthalten, übereinstimmen, da dies die Folgen von Bytes falsch interpretieren würde.würde funktionieren, aber nur wenn
LC_ALL
nichts anderes eingestellt ist (was übersteuern würdeLC_COLLATE
). Sie müssen also möglicherweise Folgendes tun:Wenn Sie nach englischen Buchstaben in einer Datei suchen möchten, die in der Codierung des Gebietsschemas codiert ist.
quelle
C
Gebietsschema wird nur benötigt, um den "portablen Zeichensatz" (ASCII 0-127) zu unterstützen, und das Verhalten für Zeichen> 127 ist technisch nicht spezifiziert . In der Praxis behandeln die meisten Programme sie als undurchsichtige Daten und leiten sie wie beschrieben weiter. Aber nicht alle: Insbesondere kann Ruby char-Daten mit Bytes> 127 verschlucken, wenn es in derC
Ländereinstellung ausgeführt wird. Ich weiß ehrlich gesagt nicht, ob das technisch "konform" ist, aber wir haben es in der Natur gesehen .perl
's\x{7FFFFFFFFFFFFFFF}
), und während der Bereich der Unicode-Codepunkte willkürlich auf U + 10FFFF beschränkt wurde (Aufgrund der UTF-16-Designbeschränkung) erkennen / produzieren einige Tools immer noch 6-Byte-Zeichen. Das habe ich mit 6-Byte-Zeichen gemeint. In der Unix-Semantik ist ein Zeichen ein Codepunkt. Ihre mehr als einen Codepunkt "Zeichen" werden allgemeiner als Graphem-Cluster bezeichnet, um sie von Zeichen zu unterscheiden.C
ist das Standardgebietsschema, "POSIX" ist der Alias von "C". Ich denke, "C" ist von ANSI-C abgeleitet. Möglicherweise definiert ANSI-C das Gebietsschema "POSIX".quelle
C
Name des Gebietsschemas von "ANSI C" abgeleitet ist.Soweit ich das beurteilen kann, verwendet OS X die Codepunkt-Sortierreihenfolge in UTF-8-Gebietsschemata, so dass dies eine Ausnahme zu einigen der in der Antwort von Stéphane Chazelas genannten Punkten darstellt.
Dies druckt 26 in OS X und 310 in Ubuntu:
Der folgende Code gibt in OS X nichts aus, was darauf hinweist, dass die Eingabe sortiert ist. Die sechs entfernten Ersatzzeichen verursachen einen unzulässigen Bytefolgenfehler.
Der folgende Code gibt in OS X nichts aus, was darauf hinweist, dass es keine zwei aufeinander folgenden Codepunkte (mindestens zwischen U + 000B und U + D7FF) mit derselben Sortierreihenfolge gibt.
(Die obigen Beispiele werden verwendet,
%b
da diesprintf \\U25
zu einem Fehler in zsh führt.)Einige Zeichen und Zeichenfolgen, die in GNU-Systemen dieselbe Sortierreihenfolge haben, haben in OS X nicht dieselbe Sortierreihenfolge. Dies druckt ① zuerst in OS X (unter Verwendung von OS X
sort
oder GNUsort
), aber but zuerst in Ubuntu:Dies druckt drei Zeilen in OS X (entweder mit OS X
sort
oder GNUsort
), aber eine Zeile in Ubuntu:quelle
Es scheint, dass es
LC_COLLATE
die "alphabetische Reihenfolge" steuert, die auch von ls verwendet wird. Das US-Gebietsschema wird wie folgt sortiert:im Grunde ignorieren die Perioden. Vielleicht bevorzugen Sie:
Das tue ich sicher. Einstellen
LC_COLLATE
,C
um dies zu erreichen. Beachten Sie, dass auch Kleinbuchstaben nach allen Großbuchstaben sortiert werden:quelle