¿Cuál podría ser una forma de recuperar una lista de todos los caracteres en una clase de caracteres determinada (como ,, blank
... ) en la ubicación actual?alpha
digit
Por ejemplo,
LC_ALL=en_GB.UTF-8 that-command blank
Lo ideal sería que en mi sistema Debian mostrara algo como:
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
Y en la configuración regional C podría mostrarse algo como:
09 U+0009 HORIZONTAL TAB
20 U+0020 SPACE
Es decir, la representación del carácter en la configuración regional en términos de matrices de bytes (como UTF-8 en el primer ejemplo y un solo byte en el segundo), el punto de código del carácter Unicode equivalente y una descripción.
Contexto
(editar) Ahora que la vulnerabilidad ha sido parcheada y divulgada hace mucho tiempo, puedo agregar un poco de contexto.
Hice esa pregunta en el momento en que estaba investigando.CVE 2014-0475. glibc
tenía un error que permitía al usuario usar configuraciones regionales como LC_ALL=../../../../tmp/evil-locale
las que se resuelven en relación con la ruta de búsqueda de configuración regional estándar del sistema y, por lo tanto, permiten usar cualquier archivo como definición de configuración regional.
Podría crear una ubicación deshonestapor ejemplo, con un solo byte por conjunto de caracteres donde se consideraron la mayoría de los caracteres, excepto s
, h
y algunos otrosespacios en blancoy eso haría que bash
se ejecute sh
mientras se analiza un archivo Debian típico /etc/bash.bashrc
(y eso podría usarse para obtener acceso al shell en un git
servidor de alojamiento, por ejemplo, siempre que bash
se use como el shell de inicio de sesión del git
usuario del servidor y que el ssh
servidor acepte LC_*
/ LANG
variables y que el atacante pueda subir archivos al servidor).
Ahora, si alguna vez encuentro una LC_CTYPE
(definición regional compilada) en /tmp/evil
, ¿cómo puedo saber que es falsa y de qué manera?
Entonces, mi objetivo es descompilar esas definiciones locales y, si no, al menos saber qué caracteres (junto con su codificación) están en una clase de caracteres determinada.
Así que con eso en mente:
- Las soluciones que analizan los archivos fuente de la configuración regional (las definiciones de configuración regional como las de
/usr/share/i18n/locale
Debian) no sirven de nada en mi caso. - Las propiedades de los caracteres Unicode son irrelevantes. Sólo me importa lo que dice el lugar. En un sistema Debian, incluso entre dos configuraciones regionales del sistema UTF-8, y mucho menos entre dos configuraciones regionales no autorizadas, la lista de caracteres en una clase puede ser diferente.
- Herramientas como
recode
,python
operl
que realizan la conversión de bytes/multibytes a/desde caracteres no se pueden usar ya que pueden (y en la práctica lo hacen) realizar la conversión de una manera diferente a la configuración regional.
Respuesta1
POSIBLE SOLUCIÓN FINAL
Así que tomé toda la información a continuación y se me ocurrió esto:
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
NOTA:
Lo uso od
como filtro final arriba por preferencia y porque sé que no trabajaré con caracteres multibyte, que no manejará correctamente. recode u2..dump
generará un resultado más parecido al especificado en la pregunta y manejará los caracteres anchos correctamente.
PRODUCCIÓN
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 DEL PROGRAMADOR
Como lo demuestro a continuación, recode
le proporcionaré su mapa de personajes completo. Según su manual, esto lo hace primero según el valor actual de la DEFAULT_CHARSET
variable de entorno, o en su defecto,funciona exactamente como usted especifica:
Cuando unjuego de caracteresEl nombre se omite o se deja vacío,
DEFAULT_CHARSET
en su lugar se utiliza el valor de la variable en el entorno. Si esta variable no está definida, larecode
biblioteca utiliza lacodificación de la configuración regional actual.EnPOSIXsistemas compatibles, esto depende del primer valor no vacío entre las variables de entornoLC_ALL, LC_CTYPE, LANG
y se puede determinar mediante el comandolocale charmap.
También vale la pena señalar recode
quees una API:
El programa nombrado
recode
es sólo una aplicación de su biblioteca de grabación. La biblioteca de grabación está disponible por separado para otros programas en C. Una buena forma de familiarizarse con la biblioteca de grabación es familiarizarse con elrecode
programa en sí.Para utilizar la biblioteca de grabación una vez instalada, un programa en C debe tener una línea:
#include <recode.h>
Para una comparación de cadenas amigable a nivel internacional Los estándares POSIX
y C
definen elstrcoll()
función:
La
strcoll()
función comparará la cadena señalada pors1
con la cadena señalada pors2
, ambas interpretadas como apropiadas para la categoría LC_COLLATE de la configuración regional actual.La
strcoll()
función no cambiará la configuración de errno si tiene éxito.Dado que no se reserva ningún valor de retorno para indicar un error, una aplicación que desee verificar situaciones de error debe establecer errno en 0, luego llamar
strcoll()
y luego verificar errno.
Aquí hay unubicado por separadoejemplo de su uso:
#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);
}
Con respecto a las POSIX
clases de personajes, ya habrás notado que usaste la C
API para encontrarlas. Para caracteres y clases Unicode puedes usarrecode's
volcado-con-nombresconjunto de caracteres para obtener el resultado deseado. De sumanual de nuevo:
Por ejemplo, el comando
recode l2..full < input
implica una conversión necesaria delatín-2aUCS-2,comovolcado-con-nombressólo está conectado desdeUCS-2.En tales casos,recode
no muestra el original. latín-2códigos en el volcado, solo los correspondientesUCS-2valores. Para dar un ejemplo más simple, el comando
echo 'Hello, world!' | recode us..dump
produce el siguiente resultado:
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)
El comentario descriptivo se proporciona en inglés y ASCII, pero si la descripción en inglés no está disponible pero sí una en francés, entonces se proporciona la descripción en francés, utilizando Latin-1. Sin embargo, si la variable de entorno
LANGUAGE
oLANG
comienza con las letrasfr, la preferencia de listado pasa al francés cuando ambas descripciones están disponibles.
Usando una sintaxis similar a la anterior combinada con suconjunto de datos de prueba incluidoPuedo obtener mi propio mapa de personajes con:
recode -q u8/test8..dump </dev/null
PRODUCCIÓN
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)
Pero para personajes comunes, recode
aparentemente no es necesario. Esto debería proporcionarle caracteres con nombre para todo el conjunto de caracteres de 128 bytes:
printf %b "$(printf \\%04o $(seq 128))" |
luit -c |
od -A n -t o1z -t a -w12
PRODUCCIÓN
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
Por supuesto, sólo se representan 128 bytes, pero eso se debe a que mi configuración regional,utf-8charmaps o no, utiliza elASCIIconjunto de caracteres y nada más. Entonces eso es todo lo que tengo. Sin embargo, si lo ejecutara sin luit
filtrarlo, od
lo revertiría e imprimiría el mismo mapa nuevamente hasta\0400.
Sin embargo, existen dos problemas importantes con el método anterior. En primer lugar, está el orden de clasificación del sistema: para configuraciones regionales que no son ASCII, los valores de bits para los conjuntos de caracteres no son simplemente una influencia seq
, lo cual, como creo, es probablemente el núcleo del problema que estás tratando de resolver.
Bueno, tr's man
la página de GNU afirma que ampliará las [:upper:]
[:lower:]
clases en orden, pero eso no es mucho.
Me imagino que se podría implementar alguna solución dura, sort
pero sería una herramienta bastante difícil de manejar para una API de programación backend.
recode
Haré esto correctamente, pero el otro día no parecías muy enamorado del programa. Quizás las ediciones de hoy arrojen una luz más amigable sobre esto o quizás no.
GNU también ofrece la gettext
biblioteca de funciones y parece ser capaz deabordar este problemaal menos por el LC_MESSAGES
contexto:
- Función:
char * bind_textdomain_codeset
(const char *domainname, const char *codeset
)La
bind_textdomain_codeset
función se puede utilizar para especificar el juego de caracteres de salida para catálogos de mensajes para el dominio. nombre de dominio. Elconjunto de códigosEl argumento debe ser válido.conjunto de códigosnombre que se puede utilizar para eliconov_abiertofunción o un puntero nulo.Si elconjunto de códigosEl parámetro es el puntero nulo,
bind_textdomain_codeset
devuelve el valor seleccionado actualmente.conjunto de códigospara el dominio con el nombre nombre de dominio. Devuelve NULL si noconjunto de códigosaún no ha sido seleccionado.La
bind_textdomain_codeset
función se puede utilizar varias veces. Si se usa varias veces con el mismo argumento de nombre de dominio, la llamada posterior anula la configuración realizada por la anterior.La
bind_textdomain_codeset
función devuelve un puntero a una cadena que contiene el nombre del conjunto de códigos seleccionado. La cadena se asigna internamente en la función y el usuario no debe cambiarla. Si el sistema se quedó sin núcleo durante la ejecución debind_textdomain_codeset
, el valor de retorno es NULL y la variable global errno se establece en consecuencia.
También puedes usar nativoCarácter Unicodecategorias, que son independientes del lenguaje y renuncian por completo a las clases POSIX, o tal vez para solicitar a las primeras que le proporcionen suficiente información para definir las segundas.
Además de las complicaciones, Unicode también ofrece nuevas posibilidades. Una es que cada carácter Unicode pertenece a un determinadocategoría.Puedes hacer coincidir un solo carácter perteneciente a la categoría "letra" con
\p{L}
. Puedes hacer coincidir un solo carácter que no pertenezca a esa categoría con\P{L}
.Nuevamente, "carácter" realmente significa "punto de código Unicode".
\p{L}
coincide con un único punto de código en la categoría "letra". Si su cadena de entrada estáà
codificada comoU+0061 U+0300
, coincidea
sin acento. Si la entrada estáà
codificada comoU+00E0
, coincideà
con el acento. La razón es que tanto el código apuntaU+0061 (a)
comoU+00E0 (à)
está en la categoría “letra”, mientras queU+0300
está en la categoría “marca”.Ahora deberías entender por qué
\P{M}\p{M}*+
es el equivalente a\X
.\P{M}
coincide con un punto de código que no es una marca de combinación, mientras que\p{M}*+
coincide con cero o más puntos de código que son marcas de combinación. Para hacer coincidir una letra que incluya signos diacríticos, utilice\p{L}\p{M}*+
. Esta última expresión regular siempre coincidirá conà
, independientemente de cómo esté codificada. El cuantificador posesivo se asegura de que retroceder no haga\P{M}\p{M}*+
coincidir una no marca sin las marcas combinadas que la siguen, lo que\X
nunca sucedería.
El mismo sitio web que proporcionó la información anterior también analizaTcl
propioPOSIX-obedienteimplementación de expresiones regulares que podría ser otra forma más de lograr su objetivo.
Y la última de las soluciones, le sugeriré que pueda consultar el LC_COLLATE
archivo en sí para obtener la información completa yen ordenmapa de caracteres del sistema. Puede que esto no parezca fácil de hacer, pero logré cierto éxito con lo siguiente después de compilarlo localedef
como se muestra a continuación:
<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 cierto que actualmente tiene fallas, pero espero que al menos demuestre la posibilidad.
AL PRIMER RUBOR
strings $_/en_GB
#OUTPUT
int_select "<U0030><U0030>"
...
END LC_TELEPHONE
Realmente no parecía mucho, pero luego comencé a notar copy
comandos en toda la lista. El archivo anterior parece copy
estar en"en_US"por ejemplo, y otro muy importante que parece que todos comparten hasta cierto punto es iso_14651_t1_common
.
Es bastante grande:
strings $_ | wc -c
#OUTPUT
431545
Aquí está la introducción a /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>;
...
Por supuesto, puedes grep
superar esto, pero podrías simplemente:
recode -lf gb
En cambio. Obtendrías algo como esto:
Dec Oct Hex UCS2 Mne BS_4730
0 000 00 0000 NU null (nul)
1 001 01 0001 SH start of heading (soh)
...
... Y MÁS
También hay un dispositivo de traducción luit
terminal UTF-8, pty
supongo que actúa como intermediario para XTerms sin soporte UTF-8. Maneja muchos cambios, como registrar todos los bytes convertidos en un archivo o como un filtro -c
simple .|pipe
Nunca me di cuenta de que había tanto en esto: las ubicaciones, los mapas de personajes y todo eso. Esto aparentemente es muyVaya cosapero supongo que todo sucede detrás de escena. Hay, al menos en mi sistema, un par de cientos man 3
de resultados relacionados para búsquedas relacionadas con la configuración regional.
Y también hay:
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
...
Eso continuará por unmuyhace mucho.
Las Xlib
funciones manejan esto todo el tiempo; luit
es parte de ese paquete.
Las Tcl_uni...
funciones también podrían resultar útiles.
Solo un poco <tab>
de finalización y man
búsquedas y he aprendido bastante sobre este tema.
Con localedef
- puedes compilar el locales
en tu I18N
directorio. El resultado es original y no es extraordinariamente útil, no se parece en charmaps
nada a él, pero puedes obtener el formato sin formato tal como lo especificaste anteriormente, como lo hice yo:
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
Luego od
puedes leerlo: bytes y cadenas:
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...<
...
Aunque está muy lejos de ganar un concurso de belleza, ese es un resultado utilizable. Y od
, por supuesto, también es tan configurable como quieras.
Supongo que también me olvidé de estos:
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
Probablemente me olvidé de ellos porque no pude hacerlos funcionar. Supongo que nunca lo uso Perl
y no sé cómo cargar un módulo correctamente. Pero las man
páginas se ven bastante bien. En cualquier caso, algo me dice que encontrarás llamar a un módulo Perl al menos un poco menos difícil que a mí. Y, nuevamente, estos ya estaban en mi computadora - y ni siquiera uso Perl. También hay algunos I18N
que recorrí con nostalgia sabiendo muy bien que tampoco conseguiría que funcionaran.
Respuesta2
Al menos en sistemas GNU, FreeBSD o Solaris, este enfoque de fuerza bruta funciona:
#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;
}
Si bien según C/POSIX, wchar_t
es un tipo opaco que no tiene relación con Unicode y solo se garantiza que cubre todos los caracteres admitidos por la configuración regional del sistema, en la práctica, en la mayoría de los sistemas que admiten Unicode, los valores corresponden a los puntos del código Unicode. y las definiciones locales se basan en Unicode.
Unicode está destinado a ser un superconjunto de todos los conjuntos de caracteres conocidos, por lo que al recorrer todos los puntos de código válidos en Unicode (0 a 0xD7FF y 0xE000 a 0x10FFFF) se deben enumerar al menos todos los caracteres admitidos por un conjunto de caracteres determinado.
Aquí, utilizamos la API estándar de configuración regional del sistema para verificar cuáles son de un tipo determinado y convertirlos a su forma codificada en la codificación de la configuración regional. Usamos perl
y su charnames
módulo solo para obtener el nombre de un punto de código Unicode determinado.
En las configuraciones regionales que utilizan codificaciones con estado como ISO-2022-JP, nos aseguramos de que el formulario codificado se muestre desde un estado inicial predeterminado.
No he encontrado un sistema que haya instalado configuraciones regionales con una codificación de caracteres con estado, pero al menos en los sistemas GNU, es posible generar algunas para poder crear una configuración regional no autorizada (y al menos las herramientas GNU no funcionan correctamente en esos locales). Por ejemplo, con una configuración regional personalizada que usa ISO-2022-JP con una ja_JP
configuración regional normal, obtengo:
$ 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
Comparar con:
$ LC_ALL=ja_JP.eucjp ~/list-type blank
09 U+0009 CHARACTER TABULATION
20 U+0020 SPACE
A1 A1 U+3000 IDEOGRAPHIC SPACE
En ISO-2022-JP, la 1B 24 42
secuencia ( \e$B
) cambia de ASCII a un estado donde los caracteres se expresan como 2 bytes (7 bits) (aquí 21 21 para ese ESPACIO IDEOGRAFICO). Mientras que en EUCJP, son los mismos bytes pero elcambio de estadose realiza invirtiendo el octavo bit ( A1 = 21 | 0x80
), lo que lo hace menos apátrida.
Eso significa que en esas codificaciones con estado, hay varias formas de escribir un carácter determinado (por ejemplo, insertando varios de esoscambio de estadosecuencias), y la secuencia mostrada por ese código anterior es solo una de ellas (la canónica de un estado predeterminado inicial).
Mientras que para una configuración regional normal, los caracteres no pueden estar fuera de 0..0xD7FF, 0xE000..0x10FFFF, para unapícaroconfiguración regional, cualquier carácter en el rango admitido por wchar_t puede ser. Por ejemplo, podría crear una configuración regional donde se incluyan los caracteres U+DCBA o U+12345678 (o serían caracteres si estuvieran permitidos).espacios en blanco. Es por eso que querrás compilar ese código para -D SUPPORT_ROGUE_LOCALES
cubrirlos, aunque eso significa que lleva mucho más tiempo escanear toda la lista.
No pude usar la solución de @mikeserv porque recode
usa sus propias conversiones, ya no se mantiene y solo admite caracteres Unicode hasta 0xFFFF, y GNU tr
al menos no funciona con caracteres de varios bytes.
no pude usar@ChrisDownya python
que no tiene interfaces para las clases de caracteres POSIX.
Probé Perl, pero es falso para puntos de código entre 128 y 255 para configuraciones regionales de varios bytes distintas de UTF-8 y no utiliza las bibliotecas de conversión del sistema.