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. glibc
hatte einen Fehler, der es dem Benutzer ermöglichte, Gebietsschemas so zu verwenden, LC_ALL=../../../../tmp/evil-locale
dass 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 s
und h
einigen anderen berücksichtigt wurdenRohlingeund das würde beim Parsen einer typischen Debian- Datei bash
ausgefü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.bashrc
git
bash
git
ssh
LC_*
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/locale
bei 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).python
perl
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 od
aus 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..dump
Es 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, recode
wird Ihnen Ihre vollständige Zeichentabelle bereitgestellt. Laut Handbuch geschieht dies zunächst gemäß dem aktuellen Wert der DEFAULT_CHARSET
Umgebungsvariable, 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_CHARSET
Variable in der Umgebung verwendet. Wenn diese Variable nicht definiert ist,recode
verwendet die Bibliothek dieKodierung des aktuellen Gebietsschemas.AnPOSIXBei kompatiblen Systemen hängt dies vom ersten nicht leeren Wert unter den Umgebungsvariablen abLC_ALL, LC_CTYPE, LANG
und kann über den Befehllocale charmap.
Bemerkenswert ist auch, recode
dass esist eine API:
Das genannte Programm
recode
ist 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 demrecode
Programm 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 POSIX
und C
Normen definieren diestrcoll()
Funktion:
Die
strcoll()
Funktion soll die Zeichenfolge, auf die zeigt,s1
mit der Zeichenfolge vergleichen, auf die zeigt.s2
Beide 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 POSIX
Zeichenklassen betrifft, haben Sie bereits bemerkt, dass Sie die C
API 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 < input
impliziert der Befehl eine notwendige Konvertierung vonLatein-2ZuUCS-2,alsDump mit Namenist nur verbunden vonUCS-2.In solchen Fällenrecode
wird 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
LANGUAGE
oder jedoch mit den Buchstaben beginntLANG
fr, 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 recode
ist 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 luit
jedoch ohne Filterung ausführen würde, od
wü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 man
Seite 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, sort
aber für eine Backend-Programmier-API wäre das ein ziemlich unhandliches Tool.
recode
wird 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 gettext
Funktionsbibliothek an und scheint in der Lage zu sein,Beheben Sie dieses Problemzumindest zum LC_MESSAGES
Kontext:
— Funktion:
char * bind_textdomain_codeset
(const char *domainname, const char *codeset
)Mit der
bind_textdomain_codeset
Funktion 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_codeset
Funktion 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_codeset
Funktion 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ässtbind_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 istU+0061 U+0300
, entspricht siea
ohne Akzent. Wenn die Eingabeà
als codiert istU+00E0
, entspricht sieà
mit Akzent. Der Grund dafür ist, dass sowohl die CodepunkteU+0061 (a)
als auchU+00E0 (à)
in der Kategorie „Buchstabe“ liegen, währendU+0300
in 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_COLLATE
Datei 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 localedef
wie 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 copy
Befehle in der gesamten Liste. Die obige Datei scheint copy
in"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 grep
dies 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
luit
Ich 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 -c
als einfacher |pipe
Filter.
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 3
verwandte 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 Xlib
Funktionen handhaben dies ständig – luit
es ist Teil dieses Pakets.
Möglicherweise sind die Tcl_uni...
Funktionen auch für Sie nützlich.
nur ein wenig <tab>
Vervollständigung und man
Suchen und ich habe ziemlich viel zu diesem Thema gelernt.
Mit localedef
- können Sie das locales
in Ihrem I18N
Verzeichnis 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 od
kö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 od
es 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 Perl
und weiß nicht, wie man ein Modul richtig lädt, schätze ich. Aber die man
Seiten 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, I18N
die 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_t
um 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 perl
und sein charnames
Modul 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_JP
Gebietsschema 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 42
Sequenz ( \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_LOCALES
um 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 recode
sie eigene Konvertierungen verwendet, nicht mehr gepflegt wird und nur Unicode-Zeichen bis 0xFFFF unterstützt und GNU tr
zumindest nicht mit Mehrbyte-Zeichen funktioniert.
Ich konnte nicht verwenden@ChrisDownsda python
es 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.