¿Cómo se representan las cadenas perl internamente? ¿Qué codificación se usa? ¿Cómo manejo diferentes codificaciones correctamente?Perl strings internals
He estado usando perl durante bastante tiempo, pero no incluye una gran cantidad de manejo de cadenas en diferentes codificaciones, y cuando encontré un problema menor que tenía algo que ver con las codificaciones usualmente recurrí a algunos acciones chamánicas
Hasta este momento, pensé en cadenas perl como secuencias de bytes, que encajaban bastante bien para mis tareas. Ahora necesito procesar algo del archivo codificado en UTF-8 y aquí comienza un problema.
En primer lugar, leí archivo en cadena como esta:
open(my $in, '<', $ARGV[0]) or die "cannot open file $ARGV[0] for reading";
binmode($in, ':utf8');
my $contents;
{
local $/;
$contents = <$in>;
}
close($in);
entonces simplemente imprimirlo:
print $contents;
y me da dos cosas: una advertencia Wide character in print at <scriptname> line <n>
y un cubo de basura en la consola. Así que puedo concluir que las cadenas perl tienen un concepto de "carácter" que puede ser "ancho" o no, pero cuando se imprimen estos caracteres "anchos" se representan en la consola como múltiples bytes, no como un solo "carácter". (Me pregunto ahora por qué toda mi experiencia previa con archivos binarios funcionó como esperaba que funcionara sin ningún problema de "carácter").
¿Por qué entonces veo basura en la consola? Si perl almacena cadenas como caracteres en alguna codificación conocida, no creo que haya un gran problema para descubrir la codificación de la consola e imprimir el texto correctamente. (Yo uso Windows, por cierto).
Si perl almacena cadenas como secuencias de caracteres de ancho variable (por ejemplo, utilizando la misma codificación UTF-8), ¿por qué se hace de esta manera? Desde mi experiencia en C, manejar cuerdas es DOLOR.
Actualización.
Utilizo dos computadoras para probar, una ejecuta Windows 7 x64 con el paquete de idioma inglés instalado, pero con la configuración regional rusa (entonces tengo cp866 como página de códigos OEM y cp1251 como ANSI) con ActivePerl 5.10.1 x64; otro ejecuta la localización rusa de Windows XP de 32 bits con Cygwin Perl 5.10.0.
Gracias a los enlaces, ahora tengo una comprensión mucho más sólida de lo que está sucediendo y cómo deben hacerse las cosas.
Por cadenas de múltiples bytes me refiero a la codificación de ancho variable. – n0rd
De todos modos, no entiendo por qué tengo que hacer la conversión explícitamente: especifiqué la codificación de datos de entrada ¿por qué tengo que tomar algunos pasos adicionales? – n0rd
Has especificado la codificación de entrada. Tú haces tus cosas. Luego, especifica la codificación de salida. Los artículos a los que me refería explican mejor, debería pensar. – dylan