Por defecto, Perl no hace ninguna transformación a los datos que recibe de una base de datos. Solo a la entrada y salida del programa.
Entonces, si quieres saber qué es lo que hay en celda, te vale con leer el contenido de la base de datos y mandarlos imprimir tal cual. Como Perl trabaja en iso-8859-1 (latin1) por defecto, no aplicará ninguna traducción de caracteres.
La salida, la entubas a una herramienta que te permita ver el contenido real de lo que sale, porque, recuerda: tu terminal de línea de comandos trabaja con una determinada codificación, así que lo que quizás estás viendo no es lo que realmente está saliendo en pantalla.
Por ejemplo:
Using text Syntax Highlighting
$ ./consulta_DB.pl explorer |hexdump -C
00000000 45 73 74 6f 20 65 73 20 75 6e 61 20 70 72 75 65 |Esto es una prue|
00000010 62 61 20 64 65 20 75 63 73 32 2e 20 c3 a1 c3 a9 |ba de ucs2. ....|
00000020 c3 ad c3 b3 c3 ba c3 b1 c3 91 0a |...........|
0000002b
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
De esta manera, sí que vemos el contenido real. Si algún carácter está tildado, lo veremos repartido entre uno y cuatro bytes (según la codificación). Y tendremos más pistas de qué es lo que estamos manejando. En concreto, este ejemplo muestra pares de bytes comenzando con 'c3', así que es posible que está en utf-8. Si lo saco en la pantalla en una terminal con codificación utf8, sale bien:
Using text Syntax Highlighting
$ ./consulta_DB.pl explorer
Esto es una prueba de ucs2. áéíóúñÑ
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Así que ya ves, debes tener en cuenta:
- la codificación que usa Perl en la salida (sabemos que es latin1, pero no nos influye, de momento)
- la codificación de los datos (que no lo sabemos)
- la codificación de la terminal en la que estás trabajando (tampoco la sabemos).
Hoy en día, la mayor parte de las terminales funcionan en utf8 (así trabajo yo en Linux desde hace años). Y entonces es un problema trabajar con Perl porque sabemos que todo lo hace en latin1. Hay que acordarse siempre de, que si tengo datos en utf8, acomodar la salida.
Si tengo este programa:
Using perl Syntax Highlighting
#!/usr/bin/env perl
print "[áéíóúñÑ]\n";
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
que he escrito en una terminal utf8 y con un editor de textos que entiende utf8, la salida parece que es correcta:
Using text Syntax Highlighting
$ ./kk.pl
[áéíóúñÑ]
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
pero solo es aparente... resulta que Perl está sacando una ristra de bytes que, al salir por la terminal, ésta los interpreta siempre como si estuvieran en utf8, y nos muestra los caracteres correctos. Pero porque a Perl no le hemos dicho cómo hemos escrito esos caracteres, solo está almacenando una ristra de bytes. Y como trabaja por defecto en latin1, no realiza ningún cambio en ellos.
Si le doy más información al programa:
Using perl Syntax Highlighting
#!/usr/bin/env perl
use utf8;
print "[áéíóúñÑ]\n";
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
con el
pragma 'use utf8;' estamos indicando que, realmente, estamos escribiendo el programa con caracteres codificados en utf8. La salida es complicada:
Using text Syntax Highlighting
$ ./kk.pl
[�������]
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
(caracteres en utf8 que indican error de codificación). Si le pedimos ayuda a hexdump, ya sabemos qué pasa:
Using text Syntax Highlighting
$ ./kk.pl|hexdump -C
00000000 5b e1 e9 ed f3 fa f1 d1 5d 0a |[.......].|
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Perl, al saber que el programa está codificado en utf8, sabe cómo traducir las cadenas de caracteres que se encuentra dentro de él. Al encontrar caracteres tildados, los transforma todos a caracteres Unicode (realmente, traduce todos los textos a Unicode). A la hora de la salida, como por defecto es en latin1, hace la traducción de Unicode a latin1, y eso es justo lo que estamos viendo: caracteres codificados en latin1.
La solución es indicarle a Perl que, además, la salida estándar debe ir también en utf8, porque así es como está funcionando la terminal:
Using perl Syntax Highlighting
#!/usr/bin/env perl
use utf8;
use open qw(:utf8 :std);
print "[áéíóúñÑ]\n";
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Y ya sale correcto. También hubiese valido con "use open ':locale';", ya que entonces Perl tomaría los valores de codificación de las variables de entorno de mi sistema. De esta manera, puedo mover el programa entre distintos sistemas y codificaciones.
¡Bienvenido al mundo de la torre de Babel!