Frage Welche Komponenten verwenden die Gebietsschemavariablen?


Ich habe gelesen, dass jedem Prozess eine Reihe von Locale-Variablen zugeordnet ist. Dies sind zum Beispiel die Gebietsschemavariablen, die mit dem Gebietsschema verknüpft sind bash Prozess auf meinem System:

$ locale
LANG="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_CTYPE="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_ALL=

Ich möchte wissen, wer diese Gebietsschemavariablen tatsächlich verwendet.

Führen Sie die C-Standardfunktionen aus (zum Beispiel: fwrite()) und die Linux-Systemaufrufe verwenden sie? Unterscheidet sich das Verhalten einiger C-Standardfunktionen oder eines Linux-Systemaufrufs je nach dem Wert einer bestimmten Gebietsschemavariablen?

Oder sind es nur bestimmte Programme, die diese Gebietsschemavariablen verwenden können? Zum Beispiel kann ich ein Programm schreiben, das Nachrichten für den Benutzer in einer anderen Sprache anzeigt, abhängig vom Wert des LANG Gebietsschema-Variable.


12
2018-05-30 14:00


Ursprung


Antworten:


Standardmäßig verwenden Cs Standardbibliotheksfunktionen das Gebietsschema "C". Sie können es in das Benutzergebietsschema umschalten, um die Gebietsschema-spezifisch zu aktivieren:

  • Charakterbehandlung
  • Zusammenstellung
  • Formatierung von Datum und Uhrzeit
  • Numerische Bearbeitung
  • Währungsformatierung
  • Nachrichten

POSIX setlocale Dokumentation enthält eine unvollständige Liste von Gebietsschema-abhängigen Funktionen, die davon betroffen sind:

catopen, exec, fprintf, fscanf, isalnum, isalpha, isblank, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, iswalnum, iswalpha, iswblank, iswcntrl, iswctype, iswdigit, iswgraph, iswlower, iswprint, iswpunct, iswspace, iswupper, iswxdigit, isxdigit, localeconv, mblen, mbstowcs, mbtowc, newlocale, nl_langinfo, perror, psiginfo, setlocale, strcoll, strérror, strfmon, strftime, strsignal, strtod, strxfrm, tolower, toupper, towlower, towupper, utilocale, wcscoll, wcstod, wcstombs, wcsxfrm, wctomb

Z.B.:

printf("%'d\n", 1000000000);
printf("Setting LC_ALL to %s\n", getenv("LANG"));
setlocale(LC_ALL, ""); // Set user-preferred locale.
printf("%'d\n", 1000000000);

Ausgänge:

1000000000
Setting LC_ALL to en_US.UTF-8
1,000,000,000

10
2018-05-30 14:14



Viele Programme legen das Gebietsschema fest und verwenden es zumindest für die Internationalisierung. Einige spezifische Beispiele:

LANG="en_GB.UTF-8"

Dies ist das Gebietsschema für jede Kategorie, die Sie nicht speziell auf etwas anderes festgelegt haben. Damit kann das System neue Gebietsschema-Variablen rückwärtskompatibel hinzufügen.

LC_COLLATE="en_GB.UTF-8"

Dies wählt aus, welche Sortierreihenfolge für Zeichenfolgen verwendet wird. Beispielsweise, CH wird als ein Brief in Spanisch betrachtet und würde danach kommen Cz. Eine C-Bibliotheksfunktion, die es verwendet, ist strcoll()und POSIX-Befehle, die enthalten ls (wenn Sie Dateien nach Namen sortieren) und sort.

LC_CTYPE="en_GB.UTF-8"

Dies bestimmt die aktuelle Zeichencodierung. In C11 können Sie dies einstellen und dann Breit-Zeichen-Eingabe und -Ausgabe verwenden, wie z wprintf(). Die Bibliothek wird transparent zwischen breiten Zeichen und dem von der Außenwelt verwendeten Zeichensatz konvertieren. Unter Windows funktioniert das immer noch nicht, es sei denn, du machst etwas extra Magie, aber anderswo ist UTF-8 zum Standard geworden. Eine zunehmende Anzahl von Programmen, wie zum Beispiel clang (ab Version 7), unterstützt nicht mehr als UTF-8.

LC_MESSAGES="en_GB.UTF-8"

Dadurch wird festgelegt, in welcher Sprache und in welchem ​​Zeichensatz lokalisierte Nachrichten angezeigt werden. In C unter Unix / Linux werden diese in der Regel von einem geladen .po Datei von der gettext Bibliothek.

LC_MONETARY="en_GB.UTF-8"

Dies beeinflusst wie strfmon()formatiert monetäre Mengen.

LC_NUMERIC="en_GB.UTF-8"

Dies bestimmt die Formatierung von Zahlen das sind keine Geldbeträge.

LC_TIME="en_GB.UTF-8"

Dies wirkt sich auf die Formatierung von Zeit aus. Versuchen LC_TIME=fr_FR.UTF-8 date in der Shell ein Beispiel zu sehen. (Oder benutzen locale -a | grep UTF um einen passenden exotischen Locale auszuwählen.) Auch ein guter Test ob deine Zeitzone und ntpd funktionieren einwandfrei.

LC_ALL=

Benutzen LANG an Stelle von. Es legt alle Gebietsschema-Kategorien gleichzeitig fest, überschreibt jedoch die Werte in allen anderen Gebietsschema-Variablen. Es besteht aus Gründen der Abwärtskompatibilität.

Zum Beispiel benutze ich LANG=en_US.utf8 auf meiner Linux-Box, aber ich überschreibe LC_TIME=en_GB.utf8 um 24 Stunden auf Englisch zu bekommen. Dies wäre nicht möglich, wenn LC_ALL wurden eingestellt.

LANG Darüber hinaus können Sie Ihre Standardeinstellungen in andere Gebietsschemainformationen übertragen, die Ihr System unterstützt, z LC_ADDRESS, LC_IDENTIFICATION, LC_RESPONSE, LC_MEASUREMENT und LC_TELEPHONE.


3
2018-05-30 17:31



Ich habe gelesen, dass jedem Prozess eine Reihe von Locale-Variablen zugeordnet ist.

Das stimmt nicht wirklich, oder zumindest ist es stark vereinfacht.

Viele Standardbibliotheksfunktionen (und nicht standardmäßige Bibliotheksfunktionen) ändern ihr Verhalten basierend auf einer Gruppe von Gebietsschemakonfigurationen, die in einem versteckten globalen Objekt innerhalb der Standardbibliotheksimplementierung verwaltet werden. (In einigen Bibliotheksimplementierungen wird die Gebietsschema-Konfiguration per Thread und nicht global unter Verwendung thread-lokaler statischer Variablen verwaltet.) Dies scheint mit einem Prozess verbunden zu sein, da normalerweise jeder Prozess eine einzige Instanz der Laufzeit der Standardbibliothek hat. aber es ist wichtig zu verstehen, dass - trotz des Aussehens - die Unterstützung von Locale Teil der Bibliothek ist und nicht der Betriebssystemkern. (Natürlich definiert nichts in irgendeinem Standard, wo die Grenzen des Kerns sind oder sogar was ein Kernel sein könnte. Sie könnten Ihr Programm "Bare Metal" ausführen oder Sie hätten ein Betriebssystem, das es für nützlich hält, die Standardbibliothek innerhalb von Systemaufrufen zu implementieren Ich spreche hier über häufige Fälle.)

Die grundlegende Gebietsschema-Konfiguration wird durch den C-Standard in Abschnitt 7.11 (des C11-Standards) definiert, der zwei Schnittstellen definiert:

  • setlocale, die die Gebietsschema-Konfiguration der Bibliothek ändert und

  • localeconv, die abfragt Teil von die Gebietsschema-Konfiguration, die es ermöglicht, dass Benutzercode den numerischen Formatierungskonventionen des Gebietsschemas entspricht (einschließlich Währungsformatierung).

Die Gebietsschema-Konfiguration ist in eine Anzahl von mehr oder weniger unabhängigen Komponenten unterteilt, die "Kategorien" genannt werden. (Die C ++ - Standardbibliothek ruft diese "Facetten" auf, die auch ein allgemein verwendetes Wort sind.) Es gibt fünf Kategorien, die vom C-Standard und eine weitere von Posix definiert werden, aber die Kategorien sind offen; Bei individuellen Standardbibliotheksimplementierungen können zusätzliche Kategorien hinzugefügt werden. Zum Beispiel hat die Gnu-Standard-C-Bibliothek, die auf den meisten Linux-Systemen verwendet wird, derzeit insgesamt 12 Kategorien. (Sehen man 7 locale auf Ihrem System für eine aktuelle Liste.)

Die Standardkategorien sind:

  • LC_CTYPE: Zeichenklassifizierung und Fallkonvertierung.
  • LC_COLLATE: Sortierreihenfolge
  • LC_MONETARY: Monetäre Formatierung
  • LC_NUMERIC: Numerische, nicht-monetäre Formatierung
  • LC_TIME: Datums- und Uhrzeitformate

und die Posix Erweiterung ist:

  • LC_MESSAGES: Formate von informativen und diagnostischen Nachrichten und interaktiven Antworten.

Abgesehen von localeconv, die nur Zugriff auf bestimmte Konfigurationen von der LC_NUMERIC und LC_MONETARY Kategorien gibt es keine Möglichkeit, eine bestimmte Konfiguration abzufragen.

Außerdem gibt es keinen Standardweg, um eine einzelne Konfiguration festzulegen. Alles, was Sie tun können, ist zu verwenden setlocale Um eine gesamte Kategorie zu konfigurieren, verwenden Sie einen libraryabhängigen und nicht standardisierten Gebietsschema-Namen (der nur eine Zeichenfolge darstellt). Genauer gesagt sind zwei Locale-Namen standardisiert:

  • Der C-Standard definiert den Gebietsschema-Namen C.

  • Posix definiert den Gebietsschema-Namen POSIX. Posix gibt jedoch an, dass das entsprechende Gebietsschema mit dem angegebenen Gebietsschema identisch sein soll C.

Die Details für die Gebietsschema-Benennung sind (oder sollten) in der locale Dokumentation für die Umgebung, in der Sie arbeiten, aber ein lokales Programm wird normalerweise nie aufrufen setlocale mit einer anderen Zeichenkettenkonstante als die Standardnamen oder die leere Zeichenkette. (Ich werde in einer Minute dazu kommen.)

Das setlocale Mit der Schnittstelle kann das Programm eine eigene Gebietsschema-Kategorie festlegen oder alle Gebietsschema-Kategorien auf denselben Gebietsschema-Namen festlegen. Es gibt auch eine Zeichenfolge zurück, die verwendet werden kann, um zu einer zuvor konfigurierten Gebietsschema-Kategorie (oder vollständigen Konfiguration) zurückzukehren.

Die Kategorienamen, die in der Liste der obigen Kategorien angezeigt werden, sind Makros, die in definiert sind <locale.h>. Ein zusätzliches Makro, LC_ALL, wird auch von dieser Header-Datei definiert: LC_ALL. Eines dieser Makros muss als erstes Argument verwendet werden setlocale.

Die C- und Posix-Standards erfordern, dass die anfängliche Gebietsschemaeinstellung beim Programmstart ist C Gebietsschema. Viele Aspekte der C locale sind standardisiert (und etwas mehr Aspekte der Posix Locale sind standardisiert). Diese Standardisierung ermöglicht es einem Programmierer, beispielsweise vorherzusagen, wie numerische Konvertierungen funktionieren.

Es ist jedoch häufig der Fall, dass ein Programmierer mit dem Benutzer des Programms mit den eigenen Gebietsschema-Einstellungen dieses Benutzers interagieren möchte. Es ist offensichtlich nicht wünschenswert, dass jedes einzelne Programm seinen eigenen idiosynkratischen Mechanismus zum Bestimmen der Gebietsschemavorgaben des Benutzers aufweist, so dass die Standardbibliothek einen Mechanismus zum Festlegen des Gebietsschemas (oder einzelner Gebietsschemakategorien) auf das Standardgebietsschema bereitstellt, das konfiguriert ist: aufrufend setlocale mit der leeren Zeichenfolge ("") als Locale-Name. Der C-Standard spezifiziert keinen bestimmten Mechanismus zum Konfigurieren dieser Information; es nimmt nur an, dass eines existiert.

(Randnotiz: Anrufen setlocale mit einem leeren String als Locale Name ist nicht das gleiche wie das Anrufen setlocale mit NULL als Gebietsschema-Name. NULL erzählt setlocale Ändern Sie keine Gebietsschemaeinstellung, aber es wird weiterhin die Zeichenfolge zurückgegeben, die dem aktuellen Gebietsschema zugeordnet ist. Dies vermeidet die Notwendigkeit einer getlocaleSchnittstelle.)

Posix gibt einen Mechanismus zum Konfigurieren von Benutzereinstellungen an und besteht auch darauf, dass (meist) standardisierte Befehlszeilenprogramme im Standardgebietsschema arbeiten. Dieser Mechanismus verwendet Umgebungsvariablen, deren Namen dem entsprechen setlocale Kategorie-Makros.

Bei einer Posix-Implementierung, wenn das Programm aufruft setlocale(LC_X, ""); Die Bibliothek wird fortfahren, um die aktuelle Umgebung zu untersuchen:

  1. Zuerst sucht es nach der Umgebungsvariablen LC_ALL. Wenn das definiert ist und einen nicht leeren Wert hat, wird es zum Definieren des Gebietsschemas verwendet.

  2. Andernfalls, wenn das erste Argument zu setlocale war nicht LC_ALL Es sucht nach der Umgebungsvariablen, deren Name mit diesem Argument übereinstimmt. Wenn das definiert ist und einen nicht leeren Wert hat, wird es zum Definieren des Gebietsschemas verwendet.

  3. Andernfalls, wenn die Umgebungsvariable LANG ist definiert und hat einen nicht-leeren Wert, es wird (in einiger implementierungsabhängiger Weise) verwendet, um einen Gebietsschema-Namen zu konstruieren. (LANG soll die Sprache des Benutzers angeben, die ein wichtiger Teil ihrer Gebietsschema-Einstellungen ist.)

  4. Schließlich wird eine systemweite Standardeinstellung verwendet.

Umgebungsvariablen werden in der Regel von der login Programm (oder GUI-Äquivalent) auf der Basis von Systemkonfigurationsdateien. (Der genaue Mechanismus variiert von Distribution zu Distribution und Dokumentation ist oft schwer zu finden.)

Wie bereits erwähnt, benötigt Posix fast alle Standard-Shell-Utilities, um das Äquivalent von setlocale(LC_ALL, ""); um in dem vom Benutzer konfigurierten Gebietsschema zu arbeiten. Die Manpage (oder eine andere Dokumentation) jedes Hilfsprogramms sollte angeben, ob es dies tut oder nicht, aber es ist vernünftig anzunehmen, dass dies der Fall ist, es sei denn, es liegen einige gegenteilige Informationen vor.

Darüber hinaus sind viele (aber nicht alle) Standardbibliothekszeichenfolgenfunktionen lokal verfügbar. Bibliotheksschnittstellen, die definitiv nicht lokalitätsbewusst sind, umfassen isdigit und isxdigit, die immer auf der Grundlage der C Gebietsschema und strcmp, die Zeichenfolgen auf die gleiche Weise wie vergleicht memcmp, Verwendung der char Wert (interpretiert als ein unsigned int) um die Sortierfolge zu bestimmen. (strcoll ist locale-bewusst, wenn Sie Vergleiche nach LC_COLLATE.) Und die Zeichenkodierungen, die für breite und mehrfarbige Zeichen verwendet werden, werden (auf nicht näher spezifizierte Weise) von der LC_CTYPE Kategorie.


2
2018-05-30 16:39