César DÃaz dijo [Sat, Apr 11, 2009 at 05:52:37PM +0200]:
Hola,
Llevo varios dÃas intentando sustituir las letras con tildes o
caracteres latinos de una palabra y ya he probado con varias soluciones
que he encontrado por Internet sin éxito.
Lo que quiero es dada por ejemplo la palabra “camión”, transformarla en
“camion”, o “España” por “Espana”. El caso es que con varias soluciones
(…)
Umh… Nuevamente -y se darán cuenta que es una óptica que me ha
marcado- creo que lo que tienes que hacer es preguntarte para qué
estás haciendo esto. Si bien hasta hace unos años (antes de que
Unicode fuera aceptado comunmente) sà podÃas hablar de ventajas de
quitar los diacrÃticos, reduciendo los caracteres de 8 a 7 bits (esto
es, para caber en el subconjunto US-ASCII), hoy esto ya no tiene
sentido.
Para ahorrarme el escribir lo que mucha gente ha escrito sin duda
mejor que yo respecto a Unicode, te sugiero fuertemente asomarte a la
siguiente liga:
http://www.joelonsoftware.com/articles/Unicode.html
The Absolute Minimum Every Software Developer Absolutely,
Positively Must Know About Unicode and Character Sets (No
Excuses!) (Joel Spolsky)
Y un poquito para poderte refirir a lo que escribo a continuación:
http://inamidst.com/stuff/unidata/
Unicode Codepoint Chart
Una de las peculiaridades que nos impone Unicode es que… ya no
existe una sóla manera de escribir las cosas. Me arriesgo a enviar
aquà caracteres que algunos clientes de correo mal configurados no
mostrarán bien. Pero bueno - ¿Ves alguna diferencia entre las
siguientes letras?
á aÌ
Son completamente distintas. La primera es un sólo caracter, una a
acentuada (U+00E1). El segundo debe verse igual, pero son dos
caracteres: Una ‘a’ sencilla (U+0061) seguida de un acento agudo
combinante (U+0301).
Una cuestión muy importante de los caracteres combinantes es que
varios de ellos pueden caer sobre de la misma letra:
aÌ…ÌÌ
Esa es una ‘a’ (U+0061) con acento agudo (U+0301), grave (U+0300) y
lÃnea superior (U+0305).
Y claro, hay muchos otros que pueden verse muy similares. Este correo
lo escribo en texto plano (no cambio de tipo de letra ni nada por el
estilo), y si el font con que lees el correo lo soporta, verás algunas
variaciones:
ï¼¥ï½“ï½”ï½ ï½…ï½“ ï½”ï½…ï½˜ï½”ï½ ï½“ï½‰ï½ï½ï½Œï½…
¿Y por qué te insisto en todo esto? Porque para Ruby y para la base de
datos, naturalmente, estas cadenas se van a representar con la
secuencia de caracteres (tÃpicamente con una codificación UTF8)
correspondiente. Incluso si los ves en la consola de Ruby (cabe
mencionar que los puntos UTF normalmente los expresas como U+xxxx,
donde xxxx es un número de 32 bits en representación hexadecimal; lo
que ves en la representación interna de Ruby en este caso es el
Unicode representado como un conjunto de bytes en UTF8, con los bytes
no-imprimibles representados en octales - La primer liga que mencioné
lo explica), te los muestra explicitando su descomposición. Por
ejemplo:
[‘á’, ‘á’, ‘aÌ€ÌÌ…’, ‘ï¼¥ï½“ï½”ï½ ï½…ï½“ ï½”ï½…ï½˜ï½”ï½ ï½“ï½‰ï½ï½ï½Œï½…’]
=> ["\303\241", “a\314\201”, “a\314\200\314\201\314\205”,
“\357\274\245\357\275\223\357\275\224\357\275\217
\357\275\205\357\275\223
\357\275\224\357\275\205\357\275\230\357\275\224\357\275\217
\357\275\223\357\275\211\357\275\215\357\275\220\357\275\214\357\275\205”]
[‘á’, ‘á’, ‘aÌ€ÌÌ…’, ‘ï¼¥ï½“ï½”ï½ ï½…ï½“ ï½”ï½…ï½˜ï½”ï½ ï½“ï½‰ï½ï½ï½Œï½…’].map {|str| str.size}
=> [2, 3, 7, 54]
Y, por último, a punto al que iba: ¿Cómo puedes compararlas o
asegurarte que una á es realmente el caracter que creÃas? Obviamente
los elementos primero y segundo -que se ven idénticos- son diferentes,
dado que su longitud en bytes es distinta. Ahora, si agregamos
caracteres de composición (tomo la aÌ€ÌÌ… como ejemplo), ¿qué pasa si
los aplicamos en un órden distinto?
comp = [‘aÌ€ÌÌ…’, ‘aÌ…ÌÌ€’, ‘á̅̀’]
=> [“a\314\200\314\201\314\205”, “a\314\205\314\201\314\200”,
“\303\241\314\205\314\200”]
comp[0] == comp[1]
=> false
comp[0] == comp[2]
=> false
comp[1] == comp[2]
=> false
Las tres grafÃas son semánticamente equivalentes, pero su
representación varÃa dado que el órden en que les puse los acentos es
distinto.
… Y nuevamente, ¿todo esto para qué? Para demostrar que no tiene
sentido intentar encontrar la única representación base, al menos no
con una sencilla tabla de equivalencias. Más bien, habrÃa que
preguntarnos si tiene sentido quitar los diacrÃticos. ¿Para qué
quieres hacerlo? Si es para facilitar las búsquedas, más bien querrás
usar una biblioteca como Soundex, mucho más elaborada que los esquemas
que han presentado ante tu pregunta.
Saludos,
–
Gunnar W. - [email protected] - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF