Befehl zum Abrufen der Liste der Zeichen in einer bestimmten Zeichenklasse im aktuellen Gebietsschema

Befehl zum Abrufen der Liste der Zeichen in einer bestimmten Zeichenklasse im aktuellen Gebietsschema

Wie könnte es möglich sein, eine Liste aller Zeichen einer bestimmten Zeichenklasse (z. B. blank, alpha, digit...) im aktuellen Gebietsschema abzurufen?

Zum Beispiel,

LC_ALL=en_GB.UTF-8 that-command blank

Im Idealfall würde auf meinem Debian-System etwa Folgendes angezeigt:

      09 U+0009 HORIZONTAL TAB
      20 U+0020 SPACE
e1 9a 80 U+1680 OGHAM SPACE MARK
e1 a0 8e U+180E MONGOLIAN VOWEL SEPARATOR
e2 80 80 U+2000 EN QUAD
e2 80 81 U+2001 EM QUAD
e2 80 82 U+2002 EN SPACE
e2 80 83 U+2003 EM SPACE
e2 80 84 U+2004 THREE-PER-EM SPACE
e2 80 85 U+2005 FOUR-PER-EM SPACE
e2 80 86 U+2006 SIX-PER-EM SPACE
e2 80 88 U+2008 PUNCTUATION SPACE
e2 80 89 U+2009 THIN SPACE
e2 80 8a U+200A HAIR SPACE
e2 81 9f U+205F MEDIUM MATHEMATICAL SPACE
e3 80 80 U+3000 IDEOGRAPHIC SPACE

Und im Gebietsschema C könnte etwa Folgendes angezeigt werden:

09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE

Das heißt, die Darstellung des Zeichens im Gebietsschema in Form von Byte-Arrays (wie UTF-8 im ersten Beispiel und ein einzelnes Byte im zweiten), der entsprechende Unicode-Zeichencodepunkt und eine Beschreibung.

Kontext

(Bearbeiten) Da die Sicherheitslücke inzwischen seit langem geschlossen und offengelegt wurde, kann ich etwas Kontext hinzufügen.

Diese Frage habe ich mir damals gestellt, als ich recherchierteCVE 2014-0475. glibchatte einen Fehler, der es dem Benutzer ermöglichte, Gebietsschemas so zu verwenden, LC_ALL=../../../../tmp/evil-localedass sie relativ zum Standardsuchpfad für das Systemgebietsschema aufgelöst werden und somit die Verwendung jeder beliebigen Datei als Gebietsschemadefinition ermöglichen.

Ich könnte ein Rogue-Gebietsschema erstellenzum Beispiel mit einem Zeichensatz mit einem Byte pro Zeichen, bei dem die meisten Zeichen außer sund heinigen anderen berücksichtigt wurdenRohlingeund das würde beim Parsen einer typischen Debian- Datei bashausgeführt werden (und das könnte verwendet werden, um beispielsweise Shell-Zugriff auf einen Hosting-Server zu erhalten, vorausgesetzt, es wird als Login-Shell des Server-Benutzers verwendet, der Server akzeptiert / -Variablen und der Angreifer kann Dateien auf den Server hochladen).sh/etc/bash.bashrcgitbashgitsshLC_*LANG

Wenn ich nun jemals eine LC_CTYPE(kompilierte Gebietsschemadefinition) in finden würde /tmp/evil, wie würde ich herausfinden, dass es sich um eine betrügerische Definition handelt und auf welche Weise?

Mein Ziel besteht also darin, diese Gebietsschemadefinitionen zu dekompilieren und, wenn das nicht gelingt, zumindest herauszufinden, welche Zeichen (und ihre Kodierung) sich in einer bestimmten Zeichenklasse befinden.

Vor diesem Hintergrund:

  • Lösungen, die sich die Quelldateien für das Gebietsschema ansehen (die Gebietsschemadefinitionen wie sie /usr/share/i18n/localebei Debian vorhanden sind), sind in meinem Fall nutzlos.
  • Unicode-Zeicheneigenschaften sind irrelevant. Mich interessiert nur, was das Gebietsschema sagt. Auf einem Debian-System kann die Liste der Zeichen in einer Klasse sogar zwischen zwei UTF-8-Systemgebietsschemas, ganz zu schweigen von Rogue-Gebietsschemas, unterschiedlich sein.
  • Tools wie oder recode, die die Byte/Multibyte-Konvertierung in/aus Zeichen durchführen, können nicht verwendet werden, da sie die Konvertierung möglicherweise auf eine andere Art und Weise als das Gebietsschema vornehmen (und dies in der Praxis auch tun).pythonperl

Antwort1

MÖGLICHE ENDLÖSUNG

Ich habe alle unten aufgeführten Informationen zur Hand genommen und bin zu folgendem Ergebnis gekommen:

for class in $(
    locale -v LC_CTYPE | 
    sed 's/combin.*//;s/;/\n/g;q'
) ; do 
    printf "\n\t%s\n\n" $class
    recode u2/test16 -q </dev/null | 
    tr -dc "[:$class:]" | 
    od -A n -t a -t o1z -w12
done

NOTIZ:

Ich verwende es odaus Vorliebe als letzten Filter oben und weil ich weiß, dass ich nicht mit Mehrbyte-Zeichen arbeiten werde, die es nicht richtig verarbeiten wird. recode u2..dumpEs erzeugt sowohl eine Ausgabe, die eher der in der Frage angegebenen entspricht, als auch breite Zeichen richtig verarbeiten.

AUSGABE

        upper

   A   B   C   D   E   F   G   H   I   J   K   L
 101 102 103 104 105 106 107 110 111 112 113 114  >ABCDEFGHIJKL<
   M   N   O   P   Q   R   S   T   U   V   W   X
 115 116 117 120 121 122 123 124 125 126 127 130  >MNOPQRSTUVWX<
   Y   Z
 131 132                                          >YZ<

        lower

   a   b   c   d   e   f   g   h   i   j   k   l
 141 142 143 144 145 146 147 150 151 152 153 154  >abcdefghijkl<
   m   n   o   p   q   r   s   t   u   v   w   x
 155 156 157 160 161 162 163 164 165 166 167 170  >mnopqrstuvwx<
   y   z
 171 172                                          >yz<

        alpha

   A   B   C   D   E   F   G   H   I   J   K   L
 101 102 103 104 105 106 107 110 111 112 113 114  >ABCDEFGHIJKL<
   M   N   O   P   Q   R   S   T   U   V   W   X
 115 116 117 120 121 122 123 124 125 126 127 130  >MNOPQRSTUVWX<
   Y   Z   a   b   c   d   e   f   g   h   i   j
 131 132 141 142 143 144 145 146 147 150 151 152  >YZabcdefghij<
   k   l   m   n   o   p   q   r   s   t   u   v
 153 154 155 156 157 160 161 162 163 164 165 166  >klmnopqrstuv<
   w   x   y   z
 167 170 171 172                                  >wxyz<

        digit

   0   1   2   3   4   5   6   7   8   9
 060 061 062 063 064 065 066 067 070 071          >0123456789<

       xdigit                                                                                          

   0   1   2   3   4   5   6   7   8   9   A   B
 060 061 062 063 064 065 066 067 070 071 101 102  >0123456789AB<
   C   D   E   F   a   b   c   d   e   f
 103 104 105 106 141 142 143 144 145 146          >CDEFabcdef<

        space

  ht  nl  vt  ff  cr  sp
 011 012 013 014 015 040                          >..... <

        print

  sp   !   "   #   $   %   &   '   (   )   *   +
 040 041 042 043 044 045 046 047 050 051 052 053  > !"#$%&'()*+<
   ,   -   .   /   0   1   2   3   4   5   6   7
 054 055 056 057 060 061 062 063 064 065 066 067  >,-./01234567<
   8   9   :   ;   <   =   >   ?   @   A   B   C
 070 071 072 073 074 075 076 077 100 101 102 103  >89:;<=>?@ABC<
   D   E   F   G   H   I   J   K   L   M   N   O
 104 105 106 107 110 111 112 113 114 115 116 117  >DEFGHIJKLMNO<
   P   Q   R   S   T   U   V   W   X   Y   Z   [
 120 121 122 123 124 125 126 127 130 131 132 133  >PQRSTUVWXYZ[<
   \   ]   ^   _   `   a   b   c   d   e   f   g
 134 135 136 137 140 141 142 143 144 145 146 147  >\]^_`abcdefg<
   h   i   j   k   l   m   n   o   p   q   r   s
 150 151 152 153 154 155 156 157 160 161 162 163  >hijklmnopqrs<
   t   u   v   w   x   y   z   {   |   }   ~
 164 165 166 167 170 171 172 173 174 175 176      >tuvwxyz{|}~<

        graph

   !   "   #   $   %   &   '   (   )   *   +   ,
 041 042 043 044 045 046 047 050 051 052 053 054  >!"#$%&'()*+,<
   -   .   /   0   1   2   3   4   5   6   7   8
 055 056 057 060 061 062 063 064 065 066 067 070  >-./012345678<
   9   :   ;   <   =   >   ?   @   A   B   C   D
 071 072 073 074 075 076 077 100 101 102 103 104  >9:;<=>?@ABCD<
   E   F   G   H   I   J   K   L   M   N   O   P
 105 106 107 110 111 112 113 114 115 116 117 120  >EFGHIJKLMNOP<
   Q   R   S   T   U   V   W   X   Y   Z   [   \
 121 122 123 124 125 126 127 130 131 132 133 134  >QRSTUVWXYZ[\<
   ]   ^   _   `   a   b   c   d   e   f   g   h
 135 136 137 140 141 142 143 144 145 146 147 150  >]^_`abcdefgh<
   i   j   k   l   m   n   o   p   q   r   s   t
 151 152 153 154 155 156 157 160 161 162 163 164  >ijklmnopqrst<
   u   v   w   x   y   z   {   |   }   ~
 165 166 167 170 171 172 173 174 175 176          >uvwxyz{|}~<

        blank

  ht  sp
 011 040                                          >. <

        cntrl

 nul soh stx etx eot enq ack bel  bs  ht  nl  vt
 000 001 002 003 004 005 006 007 010 011 012 013  >............<
  ff  cr  so  si dle dc1 dc2 dc3 dc4 nak syn etb
 014 015 016 017 020 021 022 023 024 025 026 027  >............<
 can  em sub esc  fs  gs  rs  us del
 030 031 032 033 034 035 036 037 177              >.........<

        punct

   !   "   #   $   %   &   '   (   )   *   +   ,
 041 042 043 044 045 046 047 050 051 052 053 054  >!"#$%&'()*+,<
   -   .   /   :   ;   <   =   >   ?   @   [   \
 055 056 057 072 073 074 075 076 077 100 133 134  >-./:;<=>?@[\<
   ]   ^   _   `   {   |   }   ~
 135 136 137 140 173 174 175 176                  >]^_`{|}~<

        alnum

   0   1   2   3   4   5   6   7   8   9   A   B
 060 061 062 063 064 065 066 067 070 071 101 102  >0123456789AB<
   C   D   E   F   G   H   I   J   K   L   M   N
 103 104 105 106 107 110 111 112 113 114 115 116  >CDEFGHIJKLMN<
   O   P   Q   R   S   T   U   V   W   X   Y   Z
 117 120 121 122 123 124 125 126 127 130 131 132  >OPQRSTUVWXYZ<
   a   b   c   d   e   f   g   h   i   j   k   l
 141 142 143 144 145 146 147 150 151 152 153 154  >abcdefghijkl<
   m   n   o   p   q   r   s   t   u   v   w   x
 155 156 157 160 161 162 163 164 165 166 167 170  >mnopqrstuvwx<
   y   z

API FÜR PROGRAMMIERER

Wie ich unten zeige, recodewird Ihnen Ihre vollständige Zeichentabelle bereitgestellt. Laut Handbuch geschieht dies zunächst gemäß dem aktuellen Wert der DEFAULT_CHARSETUmgebungsvariable, oder, falls dies nicht möglich ist,funktioniert genau wie Sie angeben:

Wenn einZeichensatzname weggelassen oder leer gelassen wird, wird stattdessen der Wert der DEFAULT_CHARSETVariable in der Umgebung verwendet. Wenn diese Variable nicht definiert ist, recodeverwendet die Bibliothek dieKodierung des aktuellen Gebietsschemas.AnPOSIXBei kompatiblen Systemen hängt dies vom ersten nicht leeren Wert unter den Umgebungsvariablen ab LC_ALL, LC_CTYPE, LANGund kann über den Befehllocale charmap.

Bemerkenswert ist auch, recodedass esist eine API:

Das genannte Programm recodeist nur eine Anwendung seiner Umcodierungsbibliothek. Die Umcodierungsbibliothek ist separat für andere C-Programme verfügbar. Eine gute Möglichkeit, sich mit der Umcodierungsbibliothek vertraut zu machen, besteht darin, sich mit dem recodeProgramm selbst vertraut zu machen.

Um die Umkodierungsbibliothek nach der Installation verwenden zu können, muss ein C-Programm die folgende Zeile enthalten:

#include <recode.h>

Für einen international verständlichen Vergleich der Saiten Die POSIXund CNormen definieren diestrcoll()Funktion:

Die strcoll()Funktion soll die Zeichenfolge, auf die zeigt, s1mit der Zeichenfolge vergleichen, auf die zeigt. s2Beide werden als der Kategorie LC_COLLATE des aktuellen Gebietsschemas entsprechend interpretiert.

strcoll()Bei Erfolg darf die Funktion die Einstellung von errno nicht ändern.

Da kein Rückgabewert zum Anzeigen eines Fehlers reserviert ist, sollte eine Anwendung, die nach Fehlersituationen suchen möchte, „errno“ auf 0 setzen, dann aufrufen und strcoll()anschließend „errno“ prüfen.

Hier ist einseparat gelegenAnwendungsbeispiel:

#include <stdio.h>
#include <string.h>

int main ()
{
   char str1[15];
   char str2[15];
   int ret;


   strcpy(str1, "abc");
   strcpy(str2, "ABC");

   ret = strcoll(str1, str2);

   if(ret > 0)
   {
      printf("str1 is less than str2");
   }
   else if(ret < 0) 
   {
      printf("str2 is less than str1");
   }
   else 
   {
      printf("str1 is equal to str2");
   }

   return(0);
}

Was die POSIXZeichenklassen betrifft, haben Sie bereits bemerkt, dass Sie die CAPI verwendet haben, um diese zu finden. Für Unicode-Zeichen und -Klassen können Sie verwendenrecode's Dump mit Namencharset, um die gewünschte Ausgabe zu erhalten. Von seinemnochmal manuell:

Beispielsweise recode l2..full < inputimpliziert der Befehl eine notwendige Konvertierung vonLatein-2ZuUCS-2,alsDump mit Namenist nur verbunden vonUCS-2.In solchen Fällen recodewird das Original nicht angezeigt Latein-2Codes im Dump, nur die entsprechendenUCS-2Werte. Um ein einfacheres Beispiel zu geben, der Befehl

 echo 'Hello, world!' | recode us..dump

erzeugt die folgende Ausgabe:

UCS2   Mne   Description

0048   H     latin capital letter h 
0065   e     latin small letter e
006C   l     latin small letter l 
006C   l     latin small letter l
006F   o     latin small letter o 
002C   ,     comma 
0020  SP     space 
0077   w     latin small letter w 
006F   o     latin small letter o 
0072   r     latin small letter r 
006C   l     latin small letter l 
0064   d     latin small letter d 
0021   !     exclamation mark 
000A   LF    line feed (lf)

Der beschreibende Kommentar wird in Englisch und ASCII angegeben. Wenn jedoch die englische Beschreibung nicht verfügbar ist, eine französische jedoch vorhanden ist, wird stattdessen die französische Beschreibung in Latin-1 angegeben. Wenn die Umgebungsvariable LANGUAGEoder jedoch mit den Buchstaben beginntLANGfr, dann wird die französische Beschreibung bevorzugt aufgelistet, wenn beide Beschreibungen verfügbar sind.

Durch die Verwendung einer ähnlichen Syntax wie oben in Kombination mitinklusive TestdatensatzIch kann meine eigene Zeichentabelle erhalten mit:

recode -q u8/test8..dump </dev/null

AUSGABE

UCS2   Mne   Description

0001   SH    start of heading (soh)
0002   SX    start of text (stx)
0003   EX    end of text (etx)    
...
002B   +     plus sign
002C   ,     comma
002D   -     hyphen-minus
...
0043   C     latin capital letter c
0044   D     latin capital letter d
0045   E     latin capital letter e
...
006B   k     latin small letter k
006C   l     latin small letter l
006D   m     latin small letter m
...
007B   (!    left curly bracket
007C   !!    vertical line
007D   !)    right curly bracket
007E   '?    tilde
007F   DT    delete (del)

Für allgemeine Zeichen recodeist dies jedoch offensichtlich nicht erforderlich. Dies sollte Ihnen benannte Zeichen für alles im 128-Byte-Zeichensatz geben:

printf %b "$(printf \\%04o $(seq 128))" | 
luit -c |
od -A n -t o1z -t a -w12

AUSGABE

 001 002 003 004 005 006 007 010 011 012 013 014  >............<
 soh stx etx eot enq ack bel  bs  ht  nl  vt  ff
...
 171 172 173 174 175 176 177                      >yz{|}~.<
   y   z   {   |   }   ~ del

Natürlich werden nur 128 Bytes dargestellt, aber das liegt daran, dass mein Gebietsschema,utf-8Charmaps oder nicht, verwendet dieASCIIcharset und nichts weiter. Das ist also alles, was ich bekomme. Wenn ich es luitjedoch ohne Filterung ausführen würde, odwürde ich es zurückrollen und dieselbe Karte erneut drucken, bis\0400.

Allerdings gibt es bei der obigen Methode zwei große Probleme. Erstens gibt es die Sortierreihenfolge des Systems - für Nicht-ASCII-Gebietsschemas sind die Bitwerte für die Zeichensätze nicht einfach zu beeinflussen seq, was meiner Meinung nach wahrscheinlich der Kern des Problems ist, das Sie zu lösen versuchen.

Nun, auf der GNU- tr's manSeite steht, dass die Klassen der Reihe nach erweitert werden [:upper:] [:lower:]– aber das ist nicht viel.

Ich könnte mir vorstellen, dass sich damit eine etwas plumpe Lösung umsetzen ließe, sortaber für eine Backend-Programmier-API wäre das ein ziemlich unhandliches Tool.

recodewird diese Sache richtig machen, aber Sie schienen neulich nicht allzu begeistert von dem Programm zu sein. Vielleicht werden die heutigen Änderungen ein freundlicheres Licht darauf werfen, vielleicht aber auch nicht.

GNU bietet auch die gettextFunktionsbibliothek an und scheint in der Lage zu sein,Beheben Sie dieses Problemzumindest zum LC_MESSAGESKontext:

— Funktion: char * bind_textdomain_codeset( const char *domainname, const char *codeset)

Mit der bind_textdomain_codesetFunktion kann der Ausgabezeichensatz für Nachrichtenkataloge für Domänen angegeben werden. Domänenname. DerCodesatzArgument muss ein gültigesCodesatzName, der verwendet werden kann für dieiconv_öffnenFunktion oder ein Nullzeiger.

Wenn dasCodesatzParameter ist der Nullzeiger, bind_textdomain_codeset gibt den aktuell ausgewähltenCodesatzfür die Domäne mit dem Namen Domänenname. Es gibt NULL zurück, wenn keineCodesatzwurde noch nicht ausgewählt.

Die bind_textdomain_codesetFunktion kann mehrmals verwendet werden. Bei mehrmaliger Verwendung mit demselben Domänennamen-Argument überschreibt der spätere Aufruf die Einstellungen des früheren Aufrufs.

Die bind_textdomain_codesetFunktion gibt einen Zeiger auf einen String zurück, der den Namen des ausgewählten Codesatzes enthält. Der String wird intern in der Funktion zugewiesen und darf vom Benutzer nicht geändert werden. Wenn das System während der Ausführung von den Kernel verlässt bind_textdomain_codeset, ist der Rückgabewert NULL und die globale Variable errno wird entsprechend gesetzt.

Sie können auch nativeUnicode-ZeichenKategorien, die sprachunabhängig sind und ganz auf die POSIX-Klassen verzichten, oder vielleicht den Aufruf der ersteren, um genügend Informationen für die Definition der letzteren zu erhalten.

Neben den Komplikationen bringt Unicode auch neue Möglichkeiten mit sich. Eine davon ist, dass jedes Unicode-Zeichen zu einem bestimmtenKategorie.Mit können Sie ein einzelnes Zeichen abgleichen, das zur Kategorie „Buchstabe“ gehört \p{L}. Mit können Sie ein einzelnes Zeichen abgleichen, das nicht zu dieser Kategorie gehört \P{L}.

Noch einmal: „Zeichen“ bedeutet eigentlich „Unicode-Codepunkt“. \p{L}entspricht einem einzelnen Codepunkt in der Kategorie „Buchstabe“. Wenn Ihre Eingabezeichenfolge à als codiert ist U+0061 U+0300, entspricht sie aohne Akzent. Wenn die Eingabe àals codiert ist U+00E0, entspricht sie àmit Akzent. Der Grund dafür ist, dass sowohl die Codepunkte U+0061 (a)als auch U+00E0 (à)in der Kategorie „Buchstabe“ liegen, während U+0300in der Kategorie „Zeichen“ liegt.

Sie sollten jetzt verstehen, warum \P{M}\p{M}*+das Äquivalent von ist \X. \P{M}trifft auf einen Codepunkt zu, der kein Kombinationszeichen ist, während \p{M}*+ trifft auf null oder mehr Codepunkte zu, die Kombinationszeichen sind. Um einen Buchstaben einschließlich aller diakritischen Zeichen zu finden, verwenden Sie \p{L}\p{M}*+. Dieser letzte reguläre Ausdruck trifft immer auf zu à, unabhängig davon, wie er codiert ist. Der Possessivquantifikator stellt sicher, dass Backtracking nicht dazu führt, \P{M}\p{M}*+dass ein Nicht-Zeichen ohne die darauf folgenden Kombinationszeichen gefunden wird, was \X nie passieren würde.

Auf derselben Website, auf der die obigen Informationen bereitgestellt wurden, wird auch Folgendes besprochen:Tcl's eigenePOSIX-konformRegex-Implementierung, die möglicherweise eine weitere Möglichkeit ist, Ihr Ziel zu erreichen.

Und als letztes unter den Lösungen schlage ich vor, dass Sie die LC_COLLATEDatei selbst für die vollständige undin OrdnungSystemzeichentabelle. Das scheint nicht ganz einfach zu sein, aber ich hatte mit dem Folgenden einige Erfolge, nachdem ich es localedefwie unten gezeigt kompiliert hatte:

<LC_COLLATE od -j2K -a -w2048 -v  | 
tail -n2 | 
cut -d' ' -f$(seq -s',' 4 2 2048) | 
sed 's/nul\|\\0//g;s/  */ /g;:s;
    s/\([^ ]\{1,3\}\) \1/\1/;ts;
    s/\(\([^ ][^ ]*  *\)\{16\}\)/\1\n/g'

 dc1 dc2 dc3 dc4 nak syn etb can c fs c rs c sp ! "
# $ % & ' ( ) * + , - . / 0 1 2
3 4 5 6 7 8 9 : ; < = > ? @ A B
C D E F G H I J K L M N O P Q R
S T U V W X Y Z [ \ ] ^ _ ` a b
c d e f g h i j k l m n o p q r
s t u v w x y z { | } ~ del soh stx etx
eot enq ack bel c ht c vt cr c si dle dc1 del

Es ist zwar derzeit noch fehlerhaft, aber ich hoffe, dass es zumindest die Möglichkeit demonstriert.

AUF DEN ERSTEN BLICK

strings $_/en_GB

#OUTPUT

int_select "<U0030><U0030>"
...
END LC_TELEPHONE

Es sah wirklich nicht nach viel aus, aber dann bemerkte ich copyBefehle in der gesamten Liste. Die obige Datei scheint copyin"en_US"zum Beispiel, und ein weiteres, wirklich großes Problem, das sie alle bis zu einem gewissen Grad gemeinsam zu haben scheinen, ist iso_14651_t1_common.

Es ist ziemlich groß:

strings $_ | wc -c

#OUTPUT
431545

Hier ist die Einleitung zu /usr/share/i18n/locales/POSIX:

# Territory:
# Revision: 1.1
# Date: 1997-03-15
# Application: general
# Users: general
# Repertoiremap: POSIX
# Charset: ISO646:1993
# Distribution and use is free, also for
# commercial purposes.
LC_CTYPE
# The following is the POSIX Locale LC_CTYPE.
# "alpha" is by default "upper" and "lower"
# "alnum" is by definiton "alpha" and "digit"
# "print" is by default "alnum", "punct" and the <U0020> character
# "graph" is by default "alnum" and "punct"
upper   <U0041>;<U0042>;<U0043>;<U0044>;<U0045>;<U0046>;<U0047>;<U0048>;\
        <U0049>;<U004A>;<U004B>;<U004C>;<U004D>;<U004E>;<U004F>;

...

Sie können grepdies natürlich tun, aber Sie könnten auch einfach Folgendes tun:

recode -lf gb

Stattdessen erhalten Sie etwa Folgendes:

Dec  Oct Hex   UCS2  Mne  BS_4730

  0  000  00   0000  NU   null (nul)
  1  001  01   0001  SH   start of heading (soh)
...

... UND MEHR

luitIch nehme an, dass es auch ein Terminal-UTF-8- Übersetzungsgerät gibt pty, das als Vermittler für XTerms ohne UTF-8-Unterstützung fungiert. Es handhabt viele Schalter – beispielsweise das Protokollieren aller konvertierten Bytes in einer Datei oder -cals einfacher |pipeFilter.

Ich habe nie gewusst, dass es so viel zu sagen gibt - die Lokalisierungen und Charakterkarten und all das. Dies ist anscheinend ein sehrgroße Sacheaber ich schätze, das alles passiert hinter den Kulissen. Es gibt - zumindest auf meinem System - ein paar hundert man 3verwandte Ergebnisse für lokalbezogene Suchen.

Und außerdem gibt es:

zcat /usr/share/i18n/charmaps/UTF-8*gz | less

    CHARMAP
<U0000>     /x00         NULL
<U0001>     /x01         START OF HEADING
<U0002>     /x02         START OF TEXT
<U0003>     /x03         END OF TEXT
<U0004>     /x04         END OF TRANSMISSION
<U0005>     /x05         ENQUIRY
...

Das wird noch eine Weile so weitergehensehrlange Weile.

Die XlibFunktionen handhaben dies ständig – luites ist Teil dieses Pakets.

Möglicherweise sind die Tcl_uni...Funktionen auch für Sie nützlich.

nur ein wenig <tab>Vervollständigung und manSuchen und ich habe ziemlich viel zu diesem Thema gelernt.

Mit localedef- können Sie das localesin Ihrem I18NVerzeichnis kompilieren. Die Ausgabe ist komisch und nicht besonders nützlich – charmapsüberhaupt nicht wie das –, aber Sie können das Rohformat genau so erhalten, wie Sie es oben angegeben haben, so wie ich es getan habe:

mkdir -p dir && cd $_ ; localedef -f UTF-8 -i en_GB ./ 

ls -l
total 1508
drwxr-xr-x 1 mikeserv mikeserv      30 May  6 18:35 LC_MESSAGES
-rw-r--r-- 1 mikeserv mikeserv     146 May  6 18:35 LC_ADDRESS
-rw-r--r-- 1 mikeserv mikeserv 1243766 May  6 18:35 LC_COLLATE
-rw-r--r-- 1 mikeserv mikeserv  256420 May  6 18:35 LC_CTYPE
-rw-r--r-- 1 mikeserv mikeserv     376 May  6 18:35 LC_IDENTIFICATION
-rw-r--r-- 1 mikeserv mikeserv      23 May  6 18:35 LC_MEASUREMENT
-rw-r--r-- 1 mikeserv mikeserv     290 May  6 18:35 LC_MONETARY
-rw-r--r-- 1 mikeserv mikeserv      77 May  6 18:35 LC_NAME
-rw-r--r-- 1 mikeserv mikeserv      54 May  6 18:35 LC_NUMERIC
-rw-r--r-- 1 mikeserv mikeserv      34 May  6 18:35 LC_PAPER
-rw-r--r-- 1 mikeserv mikeserv      56 May  6 18:35 LC_TELEPHONE
-rw-r--r-- 1 mikeserv mikeserv    2470 May  6 18:35 LC_TIME

Dann odkönnen Sie es lesen - Bytes und Zeichenfolgen:

od -An -a -t u1z -w12 LC_COLLATE | less

 etb dle enq  sp dc3 nul nul nul   T nul nul nul
  23  16   5  32  19   0   0   0  84   0   0   0  >... ....T...<
...

Obwohl es noch weit davon entfernt ist, einen Schönheitswettbewerb zu gewinnen, ist das ein brauchbares Ergebnis. Und odes ist natürlich auch so konfigurierbar, wie Sie es wünschen.

Ich glaube, ich habe auch Folgendes vergessen:

    perl -mLocale                                                                                       

 -- Perl module --
Locale::Codes                    Locale::Codes::LangFam           Locale::Codes::Script_Retired
Locale::Codes::Constants         Locale::Codes::LangFam_Codes     Locale::Country
Locale::Codes::Country           Locale::Codes::LangFam_Retired   Locale::Currency
Locale::Codes::Country_Codes     Locale::Codes::LangVar           Locale::Language
Locale::Codes::Country_Retired   Locale::Codes::LangVar_Codes     Locale::Maketext
Locale::Codes::Currency          Locale::Codes::LangVar_Retired   Locale::Maketext::Guts
Locale::Codes::Currency_Codes    Locale::Codes::Language          Locale::Maketext::GutsLoader
Locale::Codes::Currency_Retired  Locale::Codes::Language_Codes    Locale::Maketext::Simple
Locale::Codes::LangExt           Locale::Codes::Language_Retired  Locale::Script
Locale::Codes::LangExt_Codes     Locale::Codes::Script            Locale::gettext
Locale::Codes::LangExt_Retired   Locale::Codes::Script_Codes      locale

Ich habe sie wahrscheinlich vergessen, weil ich sie nicht zum Laufen bekommen habe. Ich benutze sie nie Perlund weiß nicht, wie man ein Modul richtig lädt, schätze ich. Aber die manSeiten sehen ganz nett aus. Irgendwie habe ich jedenfalls das Gefühl, dass Sie den Aufruf eines Perl-Moduls zumindest etwas einfacher finden werden als ich. Und, noch einmal, diese waren bereits auf meinem Computer – und ich benutze Perl nie. Es gibt auch einige, I18Ndie ich wehmütig durchgescrollt habe, obwohl ich genau wusste, dass ich sie auch nicht zum Laufen bekommen würde.

Antwort2

Zumindest auf GNU-, FreeBSD- oder Solaris-Systemen funktioniert dieser Brute-Force-Ansatz:

#include <wctype.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  unsigned long i;
  int need_init;
  wctype_t type;
  FILE* to_perl;

  setlocale(LC_ALL,"");
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <type>\n", (argc?argv[0] : "???"));
    exit(1);
  }
  if (!(type = wctype(argv[1]))) {
    fprintf(stderr, "Invalid type: \"%s\"\n", argv[1]);
    exit(1);
  }

  need_init = wctomb(0, 0);

  to_perl = popen("perl -Mcharnames=full -ane '"
                  "printf \"%17s U+%04X %s\n\", join(\" \", @F[1..$#F]),"
                  "$F[0], charnames::viacode($F[0])'", "w");

#ifdef SUPPORT_ROGUE_LOCALES
  for(i=0; i<=0x7fffffff; i++) {
#else
  for(i=0; i<=0x10ffff; i++) {
    if (i == 0xd800) i = 0xe000; /* skip UTF-16 surrogates */
#endif
    if (iswctype(i, type)) {
      int n;
      unsigned char buf[1024];

      if (need_init) wctomb(0, 0);
      n = wctomb(buf, i);

      if (n > 0) {
        int c;
        fprintf(to_perl, "%lu", i);
        for (c = 0; c < n; c++)
          fprintf(to_perl, " %02X", buf[c]);
        putc('\n', to_perl);
      }
    }
  }
  pclose(to_perl);
  return 0;
}

Während es sich gemäß C/POSIX wchar_tum einen undurchsichtigen Typ handelt, der keine Beziehung zu Unicode hat und nur garantiert alle von der Gebietsschemaeinstellung des Systems unterstützten Zeichen abdeckt, entsprechen die Werte in der Praxis in den meisten Systemen, die Unicode unterstützen, den Unicode-Codepunkten und die Gebietsschemadefinitionen selbst basieren auf Unicode.

Unicode ist als Obermenge aller bekannten Zeichensätze gedacht. Wenn also alle gültigen Codepunkte in Unicode (0 bis 0xD7FF und 0xE000 bis 0x10FFFF) durchlaufen werden, sollten zumindest alle von einem bestimmten Zeichensatz unterstützten Zeichen aufgelistet werden.

Hier verwenden wir die Locale-Standard-API des Systems, um zu prüfen, welche von einem bestimmten Typ sind, und um sie in ihre codierte Form in der Locale-Kodierung zu konvertieren. Wir verwenden perlund sein charnamesModul nur, um den Namen von einem bestimmten Unicode-Codepunkt abzurufen.

Bei Gebietsschemata, die zustandsbehaftete Kodierungen wie ISO-2022-JP verwenden, stellen wir sicher, dass die kodierte Form von einem standardmäßigen Anfangszustand aus angezeigt wird.

Ich habe kein System gefunden, auf dem Gebietsschemas mit einer zustandsabhängigen Zeichenkodierung installiert waren, aber zumindest auf GNU-Systemen ist es möglich, einige zu generieren, sodass ein Rogue-Gebietsschema erstellt werden könnte (und zumindest funktionieren GNU-Tools in diesen Gebietsschemas nicht richtig). Mit einem benutzerdefinierten Gebietsschema, das ISO-2022-JP mit einem normalen ja_JPGebietsschema verwendet, erhalte ich beispielsweise:

$ LOCPATH=$PWD LC_ALL=ja_JP.ISO-2022-JP ~/list-type blank
       09 U+0009 CHARACTER TABULATION
       20 U+0020 SPACE
   1B 24 42 21 21 U+3000 IDEOGRAPHIC SPACE

Vergleichen mit:

$ LC_ALL=ja_JP.eucjp ~/list-type blank
       09 U+0009 CHARACTER TABULATION
       20 U+0020 SPACE
    A1 A1 U+3000 IDEOGRAPHIC SPACE

In ISO-2022-JP wechselt die 1B 24 42Sequenz ( \e$B) von ASCII zu einem Zustand, in dem Zeichen als 2 (7-Bit) Bytes ausgedrückt werden (hier 21 21 für diesen IDEOGRAPHISCHEN RAUM). Während es in EUCJP die gleichen Bytes sind, aber dieZustandsumschaltungwird durch das Umdrehen des 8. Bits ( A1 = 21 | 0x80) erreicht, wodurch es zustandsloser wird.

Das bedeutet, dass es in diesen zustandsbehafteten Kodierungen mehrere Möglichkeiten gibt, ein bestimmtes Zeichen zu schreiben (zum Beispiel durch Einfügen mehrerer dieserZustandsumschaltungSequenzen), und die oben durch den Code angezeigte Sequenz ist nur eine davon (die kanonische aus einem anfänglichen Standardzustand).

Während bei einem normalen Gebietsschema die Zeichen nicht außerhalb von 0..0xD7FF, 0xE000..0x10FFFF liegen können,Schurkelocale, jedes Zeichen im von wchar_t unterstützten Bereich kann sein. Ich könnte zum Beispiel ein Locale erstellen, in dem U+DCBA oder U+12345678 Zeichen (oder Zeichen wären, wenn sie erlaubt wären) sindRohlinge. Aus diesem Grund sollten Sie den Code mit kompilieren, -D SUPPORT_ROGUE_LOCALESum diese abzudecken. Das bedeutet allerdings, dass das Scannen der gesamten Liste wesentlich mehr Zeit in Anspruch nimmt.

Ich konnte die Lösung von @mikeserv nicht verwenden, da recodesie eigene Konvertierungen verwendet, nicht mehr gepflegt wird und nur Unicode-Zeichen bis 0xFFFF unterstützt und GNU trzumindest nicht mit Mehrbyte-Zeichen funktioniert.

Ich konnte nicht verwenden@ChrisDownsda pythones keine Schnittstellen zu den POSIX-Zeichenklassen gibt.

Ich habe Perl ausprobiert, aber es ist für Codepunkte zwischen 128 und 255 für andere Mehrbyte-Gebietsschemas als UTF-8 falsch und verwendet nicht die Konvertierungsbibliotheken des Systems.

verwandte Informationen