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 odcomme 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..dumpva à 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, recodevous fournira votre carte de personnage complète. Selon son manuel, il le fait d'abord en fonction de la valeur actuelle de la DEFAULT_CHARSETvariable 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_CHARSETvariable dans l'environnement est utilisée à la place. Si cette variable n'est pas définie, la recodebibliothè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, LANGet peut être déterminée via la commandelocale charmap.
Il convient également de noter recodequ'il s'agit d'une API :
  Le programme nommé recoden'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 recodeprogramme 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 POSIXet Cdéfinissent la strcoll()fonction:
  La strcoll()fonction doit comparer la chaîne pointée par s1la 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 POSIXclasses de personnages, vous avez déjà noté que vous avez utilisé l' CAPI 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 < inputimplique 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, recoden'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 LANGUAGEou l' LANGenvironnement 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, recoden'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 luitfiltrer, odje 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 sequence, ce qui, comme je pense, est probablement au cœur du problème que vous essayez de résoudre.
Eh bien, la tr's manpage 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 sortmais ce serait un outil plutôt lourd pour une API de programmation backend.
recodefera 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 gettextbibliothèque de fonctions, et il semble pouvoir résoudre ce problème au moins pour le LC_MESSAGEScontexte:
  - Fonction: char * bind_textdomain_codeset( const char *domainname,
  const char *codeset)
  
  La bind_textdomain_codesetfonction 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_codesetfonction 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_codesetfonction 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 asans 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+0300dans 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 Tclpropre 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_COLLATEfichier 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é localedefcomme 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 copycommandes dans la liste. Le fichier ci-dessus semble copydans "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 grepbien 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 luitterminal de ptytraduction 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 -ccomme un simple |pipefiltre.
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 3ré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 Xlibfonctions gèrent cela tout le temps - font luitpartie de ce package.
Les Tcl_uni...fonctions pourraient également s'avérer utiles.
juste un peu d' <tab>achèvement et de manrecherches et j'ai beaucoup appris sur ce sujet.
Avec localedef- vous pouvez compiler le localesdans votre I18Nrépertoire. La sortie est géniale et pas extraordinairement utile - pas du charmapstout - 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 odvous 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 odest 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 Perlet je ne sais pas comment charger un module correctement je suppose. Mais les manpages 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