• Publicidad

Problema con tildes y eñes

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Problema con tildes y eñes

Notapor robenavente » 2007-09-11 22:33 @981

Hola a todos, soy nuevo en Perl y aquí en el foro. Les comento que he tenido un problema con un script de Perl que estoy haciendo que básicamente consiste en que al usar la función split en una cadena que contenga eñes o tildes el resultado es un carácter desconocido. Tratando de detectar el problema hice el siguiente script para graficarlo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
$a="ñ";
@au= split (//, $a);
print "@au\n";
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


cuya salida es "??". Al cambiar la última línea por print @au me devuelve correctamente una ñ. Sin embargo si quiero ocupar el arreglo @au en cualquier cosa no me reconoce la ñ. He buscado bastante y no he podido dar con el problema. En mi archivo /etc/environment tengo las locales:

Código: Seleccionar todo
LANGUAGE="es_CL:es_ES:es:en_GB:en"
LANG="es_CL.UTF-8"
LC_ALL=""


Que según encontré es la configuración correcta. Dentro de mi ignorancia del tema no sé qué otro dato pudiese servirles para ver dónde está el problema, pero cualquier dato que pudiese ser útil me lo dicen y listo. Probablemente no es un problema tan complicado, pero he leído bastante y buscado en este foro y Google problemas similares y no he dado con respuesta, así que como última opción he recurrido al foro. Espero que alguien me pueda ayudar. ¡ Saludos !
robenavente
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2007-09-11 21:42 @946

Publicidad

Una idea

Notapor bishop13 » 2007-09-12 04:46 @240

No sé mucho de casi nada, pero para diagnosticar mejor tu problema habría que saber si ese '??' es un problema de la visualización de tu terminal o bien si los tiros van por otro lado. Prueba a redirigir la salida de tu script a un archivo o a imprimir directamente en un archivo, en vez de en la salida estandar. Si aparece una eñe, el problema es de tu intérprete de comandos (putty, bash, ksh, cmd, etc.).
Es sólo una idea. ¡¡Suerte!!
bishop13
Perlero nuevo
Perlero nuevo
 
Mensajes: 1
Registrado: 2007-09-12 04:39 @235

Notapor explorer » 2007-09-12 06:26 @309

La explicación es que estás usando codificación en UTF8, por lo que la eñe se convierte en dos caracteres.

Luego, al sacarlo entre comillas dobles, Perl muestra todo el array (dos caracteres) separados por el delimitador $", pero tu terminal no sabe interpretarlos.

En cambio, cuando lo haces sin comillas dobles, salen todos los elementos juntos, y tu terminal cree recibir un solo carácter utf8, por lo que muestra la eñe.

Es muy importante saber:
* con qué codificación estás recibiendo la entrada
* con qué codificación estás escribiendo la salida
* con qué codificación estás programando.

En perlunicode se comenta un poco todo esto, en la sección Byte and Character Semantics.

Posibles soluciones...
* Si estás seguro que sólo quieres manejar bytes, use bytes;
* Si vas a escribir caracteres como la eñe o acentuados dentro del código, use utf8;
* Si vas a leer o escribir ficheros con alguna determinada codificación y la quieres pasar a otra, use encoding, Encode y PerlIO, y otras.

De lectura obligada: perluniintro. Un resumen es que a partir de v5.8, Perl maneja utf8 internamente en su manejo de strings, pero no en los identificadores ni en los literales. Por ejemplo, podríamos escribir:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use utf8;
$carácter = "ñ";
print length $carácter;
print "$carácter\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
y lo grabamos en disco también en formato utf8, el programa funcionará y nos devolverá un uno y una eñe (en formato utf8). Observa también que tenemos una variable escrita con caracteres utf8: $carácter. Todo esto es posible porque hemos puesto use utf8; al principio, y con eso Perl maneja esos caracteres en las dos situaciones: identificadores y literales.

No es recomendable (todavía) usar este tipo de programación, pero Perl ya está preparado para el futuro.

Si nos das algún detalle más de lo que quieres hacer, quizás la solución sea muy sencilla.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor robenavente » 2007-09-12 10:17 @470

Hola, muchas gracias por las respuestas ¡y tan rápido!. Bueno le he estado echando un vistazo a toda la info y les cuanto como me ha ido:
* Si redirijo la salida a un archivo al leerlo (como utf8) me devuelve nuevamente "??" y como bytes me devuelve "Ã ±". Mi terminal me lee correctamente nombres de archivos con ñ y tildes así que no sé si va por ahí el problema.

* Probé con "use bytes" (sacando la á del código) y la salida del código que diste es "2ñ". Pero al usar "use utf8" la salida es "1?"

* Guardando el archivo de texto como utf8 el resultado es el mismo.

* Bueno la verdad la idea era que mi programa identificara si el carácter de una cadena era una cierta letra (por ejemplo la ñ) y la cambiara por otra (por ejemplo una h). Pero como a la vez, si era h, debía cambiarla por otra, no podía usar un s/n/h/gi, por ejemplo (cosa que si funciona bien) puesto que luego habrían más h de las que habían originalmente. La única solución que se me ocurrió era buscar carácter por carácter (por eso el split //) y cambiarlo en caso de que corresponda, cuestión que funciona, pero una vez que hago el split no es posible que reconozca la ñ, creo recordar que si hacía un if ($letra eq "ñ" ) me consideraba la letra como si fuera ñ. Bueno eso, seguiré revisando la documentación a ve si encuentro algo.

¡Gracias nuevamente!
robenavente
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2007-09-11 21:42 @946

Notapor explorer » 2007-09-12 11:12 @508

robenavente escribiste:* Si redirijo la salida a un archivo al leerlo (como utf8) me devuelve nuevamente "??" y como bytes me devuelve "Ã ±". Mi terminal me lee correctamente nombres de archivos con ñ y tildes así que no sé si va por ahí el problema.

Los caracteres "??" son los correspondientes a la eñe en utf8 ("Ã ±") pero tu terminal no es capaz de representarlos por alguna razón distinta a la de pintarlos como bytes, que sí pinta correctamente los 2 bytes que forman a la eñe en utf8. Quiere esto decir que tu terminal Y tu editor de textos ha escrito dentro del código fuente del Perl una eñe en utf8, y por lo tanto, para Perl son DOS caracteres (dos bytes): porque no sabe que el literal "ñ" que has escrito en realidad solo es un carácter. Tu ves solamente uno porque eso es lo que escribes y lo que te muestra tu editor de textos y tu terminal, pero DENTRO del código Perl hay dos bytes. Y Perl lo tratará de esa manera y mostrará dos bytes/caracteres.

robenavente escribiste:* Probé con "use bytes" (sacando la á del código) y la salida del código que diste es "2ñ". Pero al usar "use utf8" la salida es "1?"
Claro, al decirle a Perl que "use utf8", le estamos indicando que todos los caracteres dentro del código fuente 'extraños' son en realidad caracteres utf8. La "ñ" entonces es ->1<- solo carácter, con dos bytes, pero Perl lo tratara como solamente ->1<-. Internamente, Perl siempre maneja utf8, pero con "use utf8" le estamos diciendo, ADEMÁS, que TAMBIÉN son utf8 los caracteres que hay en los literales (cadenas de texto explícitas) y en los identificadores que usemos (podríamos escribir un programa Perl en chino o japonés). Ejemplo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use utf8;
$una_eñe = "ñ";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El que no te salga la eñe en pantalla, me preocupa más. Perl dice que, efectivamente, hay un solo carácter, pero al sacarlo, la terminal no se entera. ¿Qué versión de Perl estás usando?

robenavente escribiste:* Guardando el archivo de texto como utf8 el resultado es el mismo.
¿Bueno o malo? :-D

Se supone que si estás en una terminal en utf8, lo grabarás de la misma manera, porque es entonces cuando se explica lo de los '?': la eñe se la mandas en tu terminal como utf8 pero el editor de texto la guarda con otra codificación, traduciendo los dos caracteres a '?'. Y al poner "use utf8" estás diciendo a Perl que la eñe es un carácter utf8, con dos bytes, PERO el fichero no lo grabas en utf8, por lo que entonces sacará el '1' junto con un carácter de la codificación en la que está grabado el fichero.

robenavente escribiste:* Bueno la verdad la idea era que mi programa identificara si el carácter de una cadena era una cierta letra (por ejemplo la ñ) y la cambiara por otra (por ejemplo una h). Pero como a la vez, si era h, debía cambiarla por otra, no podía usar un s/n/h/gi, por ejemplo (cosa que si funciona bien) puesto que luego habrían más h de las que habían originalmente. La única solución que se me ocurrió era buscar carácter por carácter (por eso el split //) y cambiarlo en caso de que corresponda, cuestión que funciona, pero una vez que hago el split no es posible que reconozca la ñ, creo recordar que si hacía un if ($letra eq "ñ" ) me consideraba la letra como si fuera ñ. Bueno eso, seguiré revisando la documentación a ve si encuentro algo.
Es que eso no es un trabajo de sustitución, sino de traducción:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

$frase = "La rosa de los vientos";
print "$frase\n";

$frase =~ tr/ao/oa/;

print "$frase\n";
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Código: Seleccionar todo
$ ./kk.pl
La rosa de los vientos
Lo raso de las vientas
Naturalmente, también puedes hacerlo leyendo carácter a carácter, bien sea con split o con substr.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor robenavente » 2007-09-12 23:59 @041

Gracias explorer, me ha quedado bastante claro de qué se trata el problema. Y me han servido bastante las lecturas que recomendaste. Quizá el problema sea la codificación en que guardo el archivo fuente. ¿Conoces algún editor en que se pueda cambiar esto de manera segura. Yo para códigos cortitos uso vim, pero no sé bien como maneja el tema de las codificaciones. Para códigos más largos en general uso SciTE, pero al ponerle una codificación utf8 el bash me devuelve:
cannot execute binary file


Probé con kate y ahí logré ejecutar el archivo pero aún no consigo visualizar la eñes.

Por otro lado estoy usando Perl v5.8.8, que me imagino que está bien...


Es que eso no es un trabajo de sustitución, sino de traducción:


¿¿¿Mencioné que soy novato??? Jajaja, efectivamente vi en un tutorial la utilidad de traducción de Perl pero nunca le presté atención y no es hasta ahora entendiendo qué hace. ;) En todo caso el problema de fondo sigue, porque ahora puedo traducir de maravilla un texto, pero no tengo cómo desplegar el resultado correctamente de ninguna forma. Por ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
$frase = "La rosa de los vientos";
print "$frase\n";
$frase =~ tr/ao/ña/;
print "$frase\n";
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Devuelve:
La rosa de los vientos
L� ras� de las vientas


Bueno y en guardando la salida en un archivo la misma cosa. Realmente no sé bien cómo solucionar este problemilla. ¡¡ Saludos! y gracias !!


edit: olvidé mencionar que agregando use utf8 al último código la salida es la misma que mencioné.
robenavente
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2007-09-11 21:42 @946

Notapor explorer » 2007-09-13 04:49 @243

Yo uso, en modo texto, el joe, y en gráfico, Eclipse, que sí me permiten cambiar la codificación de los fuentes.

El error que te devuelve si lo grabas como utf8 con el SciTE, me recuerda que me lo daba a mí, en otra ocasión, porque la primera línea del código fuente no era el shebang (#!) y/o había un carácter extraño en esa primera línea.

Viendo el resultado de la ejecución yo lo veo correcto: Perl está devolviendo el carácter correspondiente al que escribiste en el código. Lo que ocurre es que hay una codificación distinta entre la que escribiste en el código, la que maneja Perl y la que te muestra la salida estándar.

Debes hacer lo siguiente: debe coincidir la codificación del editor de texto con la presencia o no de la línea utf8, junto con la codificación del terminal que ofrece la salida.

Como tu sistema trabaja en utf8, la recomendación es que sigas trabajando en ella. O editar los locales para trabajar en otra. Yo, hasta el año pasado, he trabajado con la ISO-8859-15 (Europa Central con el €).

Hoy en día lo recomendable es usar el utf8, aunque eso significa que nos alejamos de aquel mundo anterior en que los caracteres eran bytes y los bytes, caracteres.

Si sigues usando utf8 en el entorno (locales), entonces debes asegurarte que usas un editor de texto que lee y graba en utf8. Después, al editar un código Perl, si en algún lugar dentro de él, usas caracteres 'extraños' y quieres que Perl los trate como tal, debes poner el use utf8;, para indicarle que hay caracteres utf8 en el código. Si no, los tratará como dos bytes cualesquiera.

A veces, lo que hago es ver el contenido del texto con un editor hexadecimal o volcarlo con el comando hexdump, para ver realmente qué es lo que hay dentro del archivo.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor robenavente » 2007-09-14 00:48 @075

El error que te devuelve si lo grabas como utf8 con el SciTE, me recuerda que me lo daba a mí, en otra ocasión, porque la primera línea del código fuente no era el shebang (#!) y/o había un carácter extraño en esa primera línea.

¿¿Recuerdas cómo lo solucionaste??, por que no hay caso con SciTE siempre me devuelve lo mismo.

Debes hacer lo siguiente: debe coincidir la codificación del editor de texto con la presencia o no de la línea utf8, junto con la codificación del terminal que ofrece la salida.


Lo hice con kate, le puse utf8 y arranqué el xterm con compatibilidad unicode y nada. Konsole permite escoger la codificación de caracteres, le puse utf8 y aún no salen las famosas eñes. ¿Será cosa del shell? Ahora estoy en eso, tratando de configurar bash para usar utf8. Comentaré como me fue... ¡Saludos!
robenavente
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2007-09-11 21:42 @946

Notapor explorer » 2007-09-14 05:51 @285

Lo solucioné borrando la línea y escribiendo una nueva.

Para lo de las eñes:
* Ejecuta el comando locale para saber qué codificación tiene tu shell. Ese locale debe coincidir con la codificación de la terminal que estés usando.
* Si, en la línea de órdenes, pulsas la tecla de la ´ñ´ y sale una ´ñ´ en pantalla (y lo mismo para los acentos), entonces la terminal está bien configurada.
* Haz un echo -n 'ñ' > kk.txt y mira a ver la longitud que tiene el fichero. Si son dos bytes, es que has grabado un carácter utf8.
* Repítelo, con un editor de textos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor robenavente » 2007-09-16 19:04 @836

Lo solucioné borrando la línea y escribiendo una nueva.


A mi no me resultó, ni con vi ni con scite :(

Ejecuta el comando locale para saber qué codificación tiene tu shell. Ese locale debe coincidir con la codificación de la terminal que estés usando.

No sé bien cual es que el que corresponde al shell, pero esta mi salida de locale:
Código: Seleccionar todo
LANG=es_CL.UTF-8
LANGUAGE=es_CL:es_ES:es:en_GB:en
LC_CTYPE="es_CL.UTF-8"
LC_NUMERIC="es_CL.UTF-8"
LC_TIME="es_CL.UTF-8"
LC_COLLATE="es_CL.UTF-8"
LC_MONETARY="es_CL.UTF-8"
LC_MESSAGES="es_CL.UTF-8"
LC_PAPER="es_CL.UTF-8"
LC_NAME="es_CL.UTF-8"
LC_ADDRESS="es_CL.UTF-8"
LC_TELEPHONE="es_CL.UTF-8"
LC_MEASUREMENT="es_CL.UTF-8"
LC_IDENTIFICATION="es_CL.UTF-8"
LC_ALL=


Hice dos archivos, kk.txt con echo y kk2.txt con vi, aquí va un ls -lh kk*.txt:

Código: Seleccionar todo
-rw-r--r-- 1 roberto roberto 3 2007-09-16 19:57 kk2.txt
-rw-r--r-- 1 roberto roberto 2 2007-09-16 19:52 kk.txt


Efectivamente usando echo ocupa 2 bytes mi ñ, mientras en vim ocupa 3. Al paracer el editor deja un espacio siempre al final del archivo... :?
robenavente
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2007-09-11 21:42 @946

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados