NAME
perlunitut - Tutorial de Unicode en Perl
DESCRIPCIÓN
Actualmente ya no es posible trabajar con cadenas de texto de manera irreflexiva. Los programas modernos deben poder comunicar caracteres acentuados o símbolos como el del euro. Esto significa que los programadores deben adquirir nuevas costumbres. Es fácil programar software compatible con Unicode, pero hacerlo bien requiere disciplina.
Hay mucho que aprender sobre juegos de caracteres y codificaciones de texto. Probablemente lo mejor sea dedicar un día entero a esta tarea, pero para aprender los conceptos básicos bastan unos pocos minutos.
Aunque estos conceptos no son tan básicos... Se supone que ya conoce la diferencia entre bytes y caracteres, y comprende (y acepta) que hay muchos juegos de caracteres y codificaciones distintos que deben especificarse cuando se utilicen en un programa. Para adquirir estos conocimientos básicos, es recomendable leer el artículo "The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)" de Joel Spolsky, en http://joelonsoftware.com/articles/Unicode.html.
En este tutorial hablamos en términos absolutos, y solo proporcionamos una visión limitada de las muchas características relacionadas con el procesamiento de cadenas de caracteres que Perl ofrece. Sin embargo, es probable que para la mayoría de los proyectos baste con esta información.
Definiciones
Para empezar es importante aclarar algunas ideas. Ésta es la parte más importante del tutorial. Nuestro enfoque puede chocar con otros que haya encontrado en Internet, pero esto se debe a que la información proporcionada por muchas fuentes no es correcta.
Es posible que tenga que leer esta sección varias veces...
Unicode
Unicode es un juego de caracteres en el que caben muchos caracteres. El valor ordinal de un carácter se denomina código de carácter (code point). En la práctica, la distinción entre los conceptos de código de carácter y carácter es difusa, por lo que se suelen utilizar ambos términos indistintamente.
Hay muchísimos códigos de carácter, pero el hardware trabaja con bytes, y un byte sólo puede representar 256 valores. En Unicode hay muchos más caracteres, por lo que necesitamos una forma de hacerlos accesibles.
Existen varias codificaciones de Unicode en competencia, de las cuales la más utilizada es UTF-8. En una codificación de Unicode se pueden utilizar varios bytes seguidos para almacenar un solo código de carácter (o carácter).
UTF-8
UTF-8 es una codificación de Unicode. Muchas personas creen que Unicode es lo mismo que UTF-8, pero se equivocan. Hay otras codificaciones de Unicode, pero UTF-8 se está convirtiendo en la codificación estándar.
En UTF-8 los primeros 128 códigos de carácter (0 a 127) son equivalentes a ASCII. Ocupan un solo byte por carácter. Para codificar los demás caracteres se utilizan entre dos y cuatro bytes mediante un esquema complejo. Afortunadamente, Perl se encarga de esto.
Cadenas de texto (cadenas de caracteres)
Las cadenas de texto, o cadenas de caracteres, están constituidas por caracteres. En este contexto, los bytes y las codificaciones son irrelevantes. Cada carácter no es más que eso: un carácter.
Con una cadena de texto puede realizar operaciones como estas:
$texto =~ s/foo/bar/;
if ($cadena =~ /^\d+$/) { ... }
$texto = ucfirst $texto;
my $numero_caracteres = length $texto;
El valor de un carácter (ord
, chr
) es el código de carácter Unicode correspondiente.
Cadenas binarias (cadenas de bytes)
Las cadenas binarias (o cadenas de bytes) están constituidas por bytes. Contienen bytes, no caracteres. La comunicación con el mundo exterior (todo lo que esté fuera del proceso Perl actual) se realiza en binario.
Con una cadena binaria puede realizar operaciones como estas:
my (@contenido_longitud) = unpack "(V/a)*", $binario;
$binario =~ s/\x00\x0F/\xFF\xF0/; # para valientes :)
print {$fh} $binario;
my $numero_bytes = length $binario;
Codificación
Codificar consiste en convertir texto a binario. Al codificar debe especificar la codificación de destino (por ejemplo, iso-8859-1
o UTF-8
). Algunas codificaciones, como las de la familia iso-8859
("alfabeto latino"), no cubren el estándar Unicode completo; los caracteres que no se pueden representar se perderán durante la conversión.
Descodificación
Descodificar consiste en convertir binario a texto. Para descodificar necesita saber la codificación que se utilizó al codificar. También es fundamental que lo que se va a descodificar sea descodificable (por ejemplo, no tiene sentido descodificar una imagen PNG en una cadena de texto).
Formato interno
Perl utiliza un formato interno, que es una codificación con la que se codifican las cadenas de texto para almacenarlas en memoria. Todas las cadenas de texto tienen este formato interno (de hecho, es el único formato de las cadenas de texto).
No tiene que preocuparse por los detalles, ya que la conversión se realiza automáticamente al descodificar y codificar.
Su nuevo kit de herramientas
Agregue al encabezado estándar del programa la línea siguiente:
use Encode qw(encode decode);
Si no le sobra energía, puede limitarse a escribir esto:
use Encode;
Flujo de E/S (el auténtico tutorial, en 5 minutos)
El flujo de entrada/salida típico de un programa es:
1. Recibir y descodificar
2. Procesar
3. Codificar y emitir los resultados
Por supuesto, si la entrada es binaria y debe permanecer así, no debe descodificarla en una cadena de texto. Pero en todos los demás casos debe hacerlo.
No es posible descodificar de manera fiable si no se sabe cómo se codificaron los datos. Si puede elegir, es recomendable utilizar UTF-8 de manera estándar.
my $foo = decode('UTF-8', get 'http://ejemplo.com/');
my $bar = decode('ISO-8859-1', readline STDIN);
my $xyzzy = decode('Windows-1251', $cgi->param('foo'));
El procesamiento se realiza igual que antes. La única diferencia es que ahora trabajamos con caracteres en lugar de bytes. Esto resulta muy útil al utilizar funciones como substr
o length
.
Es importante comprender que en una cadena de texto no hay bytes. Por supuesto, Perl utiliza su propia codificación para almacenar la cadena en memoria, pero el usuario no tiene que conocer los detalles. Si necesita el número de bytes para algo, debe calcularlo en el paso 3, después de codificar la cadena. Así podrá saber exactamente cuántos bytes hay en la cadena generada.
La sintaxis para codificar cadenas de texto en cadenas binarias es tan sencilla como la sintaxis de descodificación:
$cuerpo_texto = encode('UTF-8', $cuerpo_texto);
Si necesita averiguar la longitud de la cadena en bytes, ahora es el momento de hacerlo. Como $cuerpo_texto
es una cadena de bytes, length
devolverá el número de bytes, en lugar del número de caracteres. Ya no se podrá saber cuál es el número de caracteres, puesto que los caracteres solo existen en las cadenas de texto.
my $numero_bytes = length $cuerpo_texto;
Y si el protocolo utilizado ofrece alguna manera de indicar al destinatario la codificación de caracteres utilizada, es muy recomendable hacerlo. Por ejemplo, el correo electrónico y HTTP son compatibles con los encabezados MIME, por lo que puede usar el encabezado Content-Type
. También se puede utilizar Content-Length
para indicar el número de bytes, un dato que siempre viene bien conocer.
"Content-Type: text/plain; charset=UTF-8",
"Content-Length: $numero_bytes"
RESUMEN
Descodifique todo lo que reciba y codifique todo lo que envíe (si son datos de tipo texto).
Preguntas y respuestas (o P+F)
Después de leer este documento también debería leer perlunifaq y, a continuación, perluniintro.
AGRADECIMIENTOS
Deseo expresar mi agradecimiento a las siguientes personas: Johan Vromans de Squirrel Consultancy. Sus diatribas contra UTF-8 en las reuniones de los Amsterdam Perl Mongers hicieron que me interesara por el tema y me propusiera aprender a utilizar de una manera segura las codificaciones de caracteres en Perl.
Gerard Goossen de TTY. Su presentación "UTF-8 in the wild" (Dutch Perl Workshop 2006) me sirvió de inspiración para publicar mis ideas y escribir este tutorial.
Todas las personas que han hecho preguntas sobre este tema en diversos canales IRC sobre Perl y que me han recordado constantemente lo necesaria que era una explicación más sencilla.
Las personas que han revisado este documento antes de su publicación: Benjamin Smith, Jan-Pieter Cornet, Johan Vromans, Lukas Mai, Nathan Gray.
AUTOR
Juerd Waalboer <#####@juerd.nl>
VEA TAMBIÉN
perlunifaq, perlunicode, perluniintro, Encode
TRADUCTORES
Joaquín Ferrero (Tech Lead)
Enrique Nell (Language Lead)