SOLUTION FINALE POSSIBLE
J'ai donc pris toutes les informations ci-dessous et trouvé ceci:
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
REMARQUE :
J'utilise od
comme filtre final ci-dessus de préférence et parce que je sais que je ne travaillerai pas avec des caractères multi-octets, qu'il ne gérera pas correctement. recode u2..dump
va à la fois générer une sortie plus semblable à celle spécifiée dans la question et gérer correctement les caractères larges.
PRODUCTION
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 DU PROGRAMMATEUR
Comme je le démontre ci-dessous, recode
vous fournira votre carte de personnage complète. Selon son manuel, il le fait d'abord en fonction de la valeur actuelle de la DEFAULT_CHARSET
variable d'environnement, ou, à défaut, il fonctionne exactement comme vous le spécifiez:
Lorsqu'un nom de jeu de caractères est omis ou laissé vide, la valeur de la DEFAULT_CHARSET
variable dans l'environnement est utilisée à la place. Si cette variable n'est pas définie, la recode
bibliothèque utilise l' encodage des paramètres régionaux en cours. Sur les systèmes compatibles POSIX , cela dépend de la première valeur non vide parmi les variables d'environnement LC_ALL, LC_CTYPE, LANG
et peut être déterminée via la commandelocale charmap.
Il convient également de noter recode
qu'il s'agit d'une API :
Le programme nommé recode
n'est qu'une application de sa bibliothèque de recodage. La bibliothèque de recodage est disponible séparément pour les autres programmes C. Un bon moyen d'acquérir une certaine familiarité avec la bibliothèque de recodage est de se familiariser avec le recode
programme lui-même.
Pour utiliser la bibliothèque de recodage une fois qu'elle est installée, un programme C doit avoir une ligne:
#include <recode.h>
Pour une comparaison de chaînes conviviale à l'échelle internationale Les normes POSIX
et C
définissent la strcoll()
fonction:
La strcoll()
fonction doit comparer la chaîne pointée par s1
la chaîne pointée par s2
, toutes deux interprétées comme appropriées à la catégorie LC_COLLATE des paramètres régionaux actuels.
La strcoll()
fonction ne doit pas modifier le paramètre errno en cas de succès.
Étant donné qu'aucune valeur de retour n'est réservée pour indiquer une erreur, une application souhaitant rechercher des situations d'erreur doit définir errno sur 0, puis appeler
strcoll()
, puis vérifier errno.
Voici un exemple distinct de son utilisation:
#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);
}
En ce qui concerne les POSIX
classes de personnages, vous avez déjà noté que vous avez utilisé l' C
API pour les trouver. Pour les caractères et les classes Unicode, vous pouvez utiliser le jeu de caractères recode's
dump-with-names pour obtenir la sortie souhaitée. De son manuel à nouveau :
Par exemple, la commande recode l2..full < input
implique une conversion nécessaire de Latin-2 à UCS-2, car le vidage avec des noms est uniquement connecté à partir de UCS-2. Dans de tels cas, recode
n'affiche pas les
codes Latin-2 d'origine dans le vidage, uniquement les valeurs UCS-2 correspondantes . Pour donner un exemple plus simple, la commande
echo 'Hello, world!' | recode us..dump
produit la sortie suivante:
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)
Le commentaire descriptif est donné en anglais et en ASCII, mais si la description en anglais n'est pas disponible mais en français, la description en français est donnée à la place, en utilisant le latin-1. Cependant, si la
variable LANGUAGE
ou l' LANG
environnement commence par les lettres fr , la préférence de listage va au français lorsque les deux descriptions sont disponibles.
En utilisant une syntaxe similaire à celle ci-dessus combinée avec son jeu de données de test inclus, je peux obtenir ma propre carte de caractères avec:
recode -q u8/test8..dump </dev/null
PRODUCTION
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)
Mais pour les personnages communs, recode
n'est apparemment pas nécessaire. Cela devrait vous donner des caractères nommés pour tout dans un jeu de caractères de 128 octets:
printf %b "$(printf \\%04o $(seq 128))" |
luit -c |
od -A n -t o1z -t a -w12
PRODUCTION
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
Bien sûr, seuls 128 octets sont représentés, mais c'est parce que mes paramètres régionaux, utf-8 charmaps ou non, utilisent le jeu de caractères ASCII et rien de plus. C'est tout ce que je reçois. Si je l'exécutais sans le luit
filtrer, od
je le retournerais et imprimerais à nouveau la même carte jusqu'à\0400.
Il existe cependant deux problèmes majeurs avec la méthode ci-dessus. Il y a d'abord l'ordre de classement du système - pour les paramètres régionaux non ASCII, les valeurs de morsure pour les jeux de caractères ne sont pas simplement in seq
uence, ce qui, comme je pense, est probablement au cœur du problème que vous essayez de résoudre.
Eh bien, la tr's man
page GNU indique qu'elle étendra les [:upper:]
[:lower:]
classes dans l'ordre - mais ce n'est pas beaucoup.
J'imagine qu'une solution lourde pourrait être implémentée avec sort
mais ce serait un outil plutôt lourd pour une API de programmation backend.
recode
fera cette chose correctement, mais vous ne sembliez pas trop amoureux du programme l'autre jour. Peut-être que les modifications d'aujourd'hui apporteront une lumière plus amicale ou non.
GNU propose également la gettext
bibliothèque de fonctions, et il semble pouvoir résoudre ce problème au moins pour le LC_MESSAGES
contexte:
- Fonction: char * bind_textdomain_codeset
( const char *domainname,
const char *codeset
)
La bind_textdomain_codeset
fonction peut être utilisée pour spécifier le jeu de caractères de sortie pour les catalogues de messages pour le domaine
nom_domaine . L' argument de jeu de codes doit être un nom de jeu de codes valide qui peut être utilisé pour la fonction iconv_open ou un pointeur nul.
Si le jeu de codes paramètre est le pointeur NULL, bind_textdomain_codeset
retourne actuellement sélectionné codeset pour le domaine avec le nom
nomdomaine . Il renvoie NULL si aucun jeu de codes n'a encore été sélectionné.
La bind_textdomain_codeset
fonction peut être utilisée plusieurs fois. S'il est utilisé plusieurs fois avec le même argument de nom de domaine, l'appel ultérieur remplace les paramètres définis par le précédent.
La bind_textdomain_codeset
fonction renvoie un pointeur sur une chaîne contenant le nom du jeu de codes sélectionné. La chaîne est allouée en interne dans la fonction et ne doit pas être modifiée par l'utilisateur. Si le système est sorti du cœur pendant l'exécution de
bind_textdomain_codeset
, la valeur de retour est NULL et la variable globale errno est définie en conséquence.
Vous pouvez également utiliser des catégories de caractères Unicode natives , qui sont indépendantes de la langue et renoncer complètement aux classes POSIX, ou peut-être faire appel aux premières pour vous fournir suffisamment d'informations pour définir les dernières.
En plus des complications, Unicode apporte également de nouvelles possibilités. La première est que chaque caractère Unicode appartient à une certaine catégorie. Vous pouvez faire correspondre un seul caractère appartenant à la catégorie "lettre" avec
\p{L}
. Vous pouvez faire correspondre un seul caractère n'appartenant pas à cette catégorie avec \P{L}
.
Encore une fois, "caractère" signifie vraiment "point de code Unicode". \p{L}
correspond à un point de code unique dans la catégorie "lettre". Si votre chaîne d'entrée est à
codée en tant que U+0061 U+0300
, elle correspond a
sans l'accent. Si l'entrée est à
codée en tant que U+00E0
, elle correspond à
à l'accent. La raison en est que les deux points de code U+0061 (a)
et U+00E0 (à)
sont dans la catégorie "lettre", tandis que U+0300
dans la catégorie "marque".
Vous devez maintenant comprendre pourquoi \P{M}\p{M}*+
est l'équivalent de \X
.
\P{M}
correspond à un point de code qui n'est pas une marque de combinaison, tandis que \p{M}*+
correspond à zéro ou plusieurs points de code qui combinent des marques. Pour faire correspondre une lettre incluant des signes diacritiques, utilisez \p{L}\p{M}*+
. Cette dernière expression régulière correspondra toujours à
, quelle que soit la façon dont elle est codée. Le quantificateur possessif s'assure que le retour arrière ne fait pas \P{M}\p{M}*+
correspondre à une non-marque sans les marques de combinaison qui le suivent, ce \X
qui ne le ferait jamais.
Le même site Web qui a fourni les informations ci - dessus discute aussi Tcl
propre d » Posix compatibles avec la norme mise en œuvre de regex qui pourrait être encore une autre façon d'atteindre votre objectif.
Enfin, parmi les solutions, je proposerai que vous puissiez interroger le LC_COLLATE
fichier lui-même pour la table de caractères système complète et en ordre . Cela peut ne pas sembler facile à faire, mais j'ai obtenu un certain succès avec ce qui suit après l'avoir compilé localedef
comme illustré ci-dessous:
<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
Il est, certes, actuellement imparfait, mais j'espère que cela démontre au moins la possibilité.
AU PREMIER BLUSH
strings $_/en_GB
#OUTPUT
int_select "<U0030><U0030>"
...
END LC_TELEPHONE
Cela ne ressemblait vraiment pas à beaucoup, mais j'ai commencé à remarquer des copy
commandes dans la liste. Le fichier ci-dessus semble copy
dans "en_US" par exemple, et un autre très gros qu'il semble qu'ils partagent tous dans une certaine mesure est iso_14651_t1_common
.
C'est assez gros:
strings $_ | wc -c
#OUTPUT
431545
Voici l'intro de /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>;
...
Vous pouvez le faire grep
bien sûr, mais vous pourriez simplement:
recode -lf gb
Au lieu. Vous obtiendriez quelque chose comme ceci:
Dec Oct Hex UCS2 Mne BS_4730
0 000 00 0000 NU null (nul)
1 001 01 0001 SH start of heading (soh)
...
... ET PLUS
Il existe également un luit
terminal de pty
traduction UTF-8 , je suppose, qui sert d'intermédiaire pour les XTerms sans prise en charge UTF-8. Il gère de nombreux commutateurs, tels que la consignation de tous les octets convertis dans un fichier ou -c
comme un simple |pipe
filtre.
Je n'ai jamais réalisé qu'il y avait tant de choses à cela - les paramètres régionaux et les cartes de personnages et tout cela. C'est apparemment un gros problème mais je suppose que tout se passe dans les coulisses. Il existe - au moins sur mon système - quelques centaines de man 3
résultats liés aux recherches liées aux paramètres régionaux.
Et il y a aussi:
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
...
Cela durera très longtemps.
Les Xlib
fonctions gèrent cela tout le temps - font luit
partie de ce package.
Les Tcl_uni...
fonctions pourraient également s'avérer utiles.
juste un peu d' <tab>
achèvement et de man
recherches et j'ai beaucoup appris sur ce sujet.
Avec localedef
- vous pouvez compiler le locales
dans votre I18N
répertoire. La sortie est géniale et pas extraordinairement utile - pas du charmaps
tout - mais vous pouvez obtenir le format brut comme vous l'avez spécifié ci-dessus comme je l'ai fait:
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
Ensuite, avec od
vous pouvez le lire - octets et chaînes:
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...<
...
Bien qu'il soit loin de gagner un concours de beauté, c'est une sortie utilisable. Et od
est aussi configurable que vous le souhaitez, bien sûr.
Je suppose que j'ai également oublié ces derniers:
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
Je les ai probablement oubliés parce que je ne pouvais pas les faire travailler. Je n'utilise jamais Perl
et je ne sais pas comment charger un module correctement je suppose. Mais les man
pages sont plutôt jolies. En tout cas, quelque chose me dit que vous trouverez qu'il est au moins un peu moins difficile d'appeler un module Perl que moi. Et, encore une fois, ils étaient déjà sur mon ordinateur - et je n'utilise même jamais Perl. Il y a aussi notamment quelques I18N
- uns que j'ai fait avec mélancolie en sachant très bien que je ne les ferais pas travailler non plus.
/usr/share/i18n/locales/i18n
... qui bien sûr provient en grande partie de la base de données de caractères Unicode. Bien sûr, ce serait bien d'avoir une commande