Salida incorrecta de UTF-8 en Perl
Tengo el siguiente programa:
<h1>! /usr/bin/perl</h1>
<p>use strict;
use warnings;
use utf8;</p>
<p>print "\x{00a0}\n";
Cuando lo ejecuto, produce la codificación UTF-8 incorrecta:
$ ./nbsp.pl | od -tx1
0000000 a0 0a
0000002
Mi expectativa sería la siguiente:
$ printf '\\u00a0\n' | od -tx1
0000000 c2 a0 0a
0000003
¿Por qué 00a0
se codifica como a0
en lugar de c2a0
como debería ser?
Lo mismo sucede cuando intento analizar datos JSON:
~~~
<h1>! /usr/bin/perl</h1>
use strict;
use warnings;
use JSON::Parse qw(parse_json);
my $json = parse_json ('{"nbsp":"\u00A0"}');
print $json->{nbsp}, "\n";
~~~
davy.ai
El problema es que la directiva
utf8
solo afecta al manejo del código fuente y las literales de texto dentro del código fuente de Perl, no a los datos externos. Cuando el script lee la cadena\x{00a0}
del código fuente, la interpreta correctamente como el carácter Unicode U+00A0 NO-BREAK SPACE, y lo codifica como la secuencia de varios bytes UTF-8c2 a0
. Sin embargo, cuando esa cadena se imprime posteriormente en la terminal, se aplica las reglas de codificación UTF-8 de la terminal, que aparentemente tratan al bytec2
como un carácter de control no imprimible y lo eliminan, dejando solo el bytea0
para representar el NO-BREAK SPACE. Del mismo modo, cuando se analizan los datos JSON, las secuencias de escape\u
son interpretadas por Perl como puntos de código Unicode, pero los caracteres resultantes no se convierten automáticamente a UTF-8. Para manejar correctamente los datos UTF-8, se puede utilizar el móduloEncode
para codificar y decodificar cadenas según sea necesario. Específicamente, se puede utilizar la funciónencode_utf8
para codificar una cadena de Perl en bytes UTF-8, y se puede utilizar la funcióndecode_utf8
para decodificar bytes UTF-8 en una cadena de Perl.