Operadores, STDOUT y Unicode

Considere el siguiente programa:

lhp@nereida:~/Lperl/src/testing$ cat -n useutf8_1.pl
     1  #!/usr/local/bin/perl -w
     2  use strict;
     3
     4  my $x = 'áéíóúñ€';
     5  print "$x\n";
     6  print length($x)."\n";
Cuando lo ejecutamos obtenemos la salida:
lhp@nereida:~/Lperl/src/testing$ useutf8_1.pl
áéíóúñ€
15
Perl tiene dos modos de procesamiento de datos: el modo byte y el modo carácter. El modo por defecto es el modo byte. Este modo es conveniente cuando se trabaja con ficheros binarios (p. ej. una imagen JPEG) y con texto codificado con un código que requiere un sólo byte por carácter como es el caso de Latin 1.

En efecto, la cadena 'áéíóúñ€' - que es una cadena unicode codificada en UTF-8 - tiene una longitud de 15 bytes. El asunto es que no es lo mismo la longitud en bytes que la longitud en caracteres cuando nos salimos de ASCII y Latin1. Si queremos que length devuelva la longitud en caracteres usemos utf8 :

lhp@nereida:~/Lperl/src/testing$ cat -n useutf8_2.pl
     1  #!/usr/local/bin/perl -w
     2  use strict;
     3  use utf8;
     4
     5  my $x = 'áéíóúñ€';
     6  print "$x\n";
     7  print length($x)."\n";
Al ejecutar obtenemos la longitud en caracteres:
lhp@nereida:~/Lperl/src/testing$ useutf8_2.pl
Wide character in print at ./useutf8_2.pl line 6.
áéíóúñ€
7
Ahora length retorna la longitud en caracteres.

Obsérvese el mensaje de advertencia. Si queremos asegurar el buen funcionamiento de la salida por STDOUT con caracteres codificados en UTF-8 debemos llamar a binmode sobre STDOUT con la capa ':utf8':

lhp@nereida:~/Lperl/src/testing$ cat -n useutf8_3.pl
     1  #!/usr/local/bin/perl -w
     2  use strict;
     3  use utf8;
     4  binmode(STDOUT, ':utf8');
     5
     6  my $x = 'áéíóúñ€';
     7  print "$x\n";
     8  print length($x)."\n";
El mensaje de advertencia desaparece:
lhp@nereida:~/Lperl/src/testing$ useutf8_3.pl
áéíóúñ€
7
Usando la opción -C del intérprete Perl se puede conseguir el mismo resultado:

lhp@nereida:~/Lperl/src/testing$ perl useutf8_1.pl
áéíóúñ€
15
lhp@nereida:~/Lperl/src/testing$ perl -Mutf8 -COE useutf8_1.pl
áéíóúñ€
7

Lea perldoc perlrun para mas información sobre estas opciones:

As of 5.8.1, the "-C" can be followed either by a number or a list of option
letters.  The letters, their numeric values, and effects are as follows;
listing the letters is equal to summing the numbers.

  I     1    STDIN is assumed to be in UTF-8
  O     2    STDOUT will be in UTF-8
  E     4    STDERR will be in UTF-8
  S     7    I + O + E
  i     8    UTF-8 is the default PerlIO layer for input streams
  o    16    UTF-8 is the default PerlIO layer for output streams
  D    24    i + o
  A    32    the @ARGV elements are expected to be strings encoded in UTF-8
  L    64    normally the "IOEioA" are unconditional,
             the L makes them conditional on the locale environment
             variables (the LC_ALL, LC_TYPE, and LANG, in the order
             of decreasing precedence) -- if the variables indicate
             UTF-8, then the selected "IOEioA" are in effect

En Perl las cadenas tienen un flag que indica si la representación interna de la cadena es utf-8. La función is_utf8 de utf8 permite conocer si una cadena esta almacenada internamente como utf-8:

pl@nereida:~/Lperltesting$ cat -n is_utf8.pl
     1  #!/usr/local/lib/perl/5.10.1/bin/perl5.10.1 -w -COE
     2  use strict;
     3  use utf8;
     4
     5  my $x = 'áéíóúñ€';
     6  my $y = 'abc';
     7  my $z = 'αβγδη';
     8  print "$x is utf8\n" if utf8::is_utf8($x);
     9  print "$y is utf8\n" if utf8::is_utf8($y);
    10  print "$z is utf8\n" if utf8::is_utf8($z);
Al ejecutar produce la salida:
pl@nereida:~/Lperltesting$ ./is_utf8.pl
áéíóúñ€ is utf8
αβγδη is utf8

Casiano Rodríguez León
Licencia de Creative Commons
Principios de Programación Imperativa, Funcional y Orientada a Objetos Una Introducción en Perl/Una Introducción a Perl
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=43.
2012-06-19