2009-03-09 12 views
92

Estoy tratando de escribir una secuencia de comandos Perl utilizando el pragma "utf8", y obtengo resultados inesperados. Estoy usando Mac OS X 10.5 (Leopard) y estoy editando con TextMate. Todas mis configuraciones tanto para mi editor como para mi sistema operativo están predeterminadas para escribir archivos en formato utf-8.¿Cómo puedo enviar UTF-8 desde Perl?

Sin embargo, cuando ingreso lo siguiente en un archivo de texto, lo guardo como un ".pl", y lo ejecuto, obtengo el "diamante con un signo de interrogación" en lugar de los caracteres que no son ASCII.

#!/usr/bin/env perl -w 

use strict; 
use utf8; 

my $str = 'Çirçös'; 
print("$str\n"); 

¿Alguna idea de lo que estoy haciendo mal? Espero obtener 'Çirçös' en la salida, pero obtengo ' ir s' en su lugar.

+1

Tal vez no es el programa ... creo que es su shell o su editor que hace la salida – n00ki3

Respuesta

141

use utf8; no habilita Unicode salida - le permite escribir Unicode en su programa. Esto, unido al programa, antes de que su estado de print():

binmode(STDOUT, ":utf8"); 

ver si eso ayuda. Eso debería hacer que STDOUT salga en UTF-8 en lugar de ASCII ordinario.

+0

No sabía de esto (solo he estado poniendo UTF8 en una base de datos, nunca imprimiéndolo). +1. –

+0

Eso funcionó, Chris. ¡Gracias! –

+1

De nada. Consulte también otra respuesta correcta: http://stackoverflow.com/questions/627661/writing-perl-code-in-utf8/627975#627975 y recuerde, TMTOWTDI. Y @Paul: si escribe UTF-8 en un archivo, probablemente debería usar binmode() en ese identificador de archivo y hacerlo "correcto" UTF-8, pero si funciona ... –

-2

Redirige la salida a un archivo de texto y prueba eso en un editor. Si se muestra bien, entonces su terminal está en falta.

+0

No, el terminal Leopard tiene $ LANG configurado en "en_US.UTF-8" de manera predeterminada. Es solo que, de forma predeterminada (por compatibilidad con versiones anteriores - blek) Perl dará como resultado caracteres 128-255 como? en lugar de Unicode, a menos que específicamente le diga que no lo haga. –

+0

También algunos editores (por ejemplo, vim) detectan automáticamente si un archivo es UTF-8 o no e intenta mostrarlo correctamente independientemente de la codificación que tenga. Abrir un archivo en el editor no es una prueba confiable. (También un buen número de editores se ejecutan en el terminal - posiblemente defectuoso -). Además, tomado literalmente, responde incorrectamente la pregunta de OP. –

-3

hacer en su shell: $ env | grep LANG

Esto probablemente mostrará que el shell no está utilizando una localización UTF-8.

+0

En realidad, se configuró en utf-8. El problema era que estaba enviando a STDOUT sin configurar binmode a utf-8; –

+2

Esto sería una preocupación ortogonal. Necesita su script de Perl para dar salida a datos correctos antes de que pueda preocuparse por cómo lo interpreta su emulador de terminal . – jrockway

75

Puede usar el open pragma.

Por ej. a continuación establece STDOUT, STDIN & STDERR utilizar UTF-8 ....

use open qw/:std :utf8/; 
+1

También es bueno. Quisiera +1 pero no tengo votos para hoy. –

+1

BTW ... Te di +1. Creo que binmode (STDOUT, ': utf8') es probablemente más correcto en esta situación. "usar abierto" tiene otros buenos usos, pero parece que no puedo encontrar cómo puedes configurarlo solo para codificar STDOUT. – draegtun

57

TMTOWTDI, optaron por el método que mejor se adapte a su forma de trabajar. Uso el método del entorno, así que no tengo que pensarlo.

En el environment:

export PERL_UNICODE=SDL 

en la command line:

perl -CSDL -le 'print "\x{1815}"'; 

o con binmode:

binmode(STDOUT, ":utf8");   #treat as if it is UTF-8 
binmode(STDIN, ":encoding(utf8)"); #actually check if it is UTF-8 

o con PerlIO:

open my $fh, ">:utf8", $filename 
    or die "could not open $filename: $!\n"; 

open my $fh, "<:encoding(utf-8)", $filename 
    or die "could not open $filename: $!\n"; 

o con el open pragma:

use open ":encoding(utf8)"; 
use open IN => ":encoding(utf8)", OUT => ":utf8"; 
+1

'-CSDL' funcionó para mí donde' binmode' solo no funcionaba. – beerbajay

+1

+1 para una respuesta completa; tenga en cuenta que 'SDL' está implícito tanto con' -C' como 'PERL_UNICODE'. El 'uso abierto ': locale'' pragma también vale la pena mencionarlo, porque es el equivalente in-script de' -C' y 'export PER_UNICODE ='. Cualquiera de estos 3 le dará soporte UTF8 para todas las transmisiones de entrada y salida (ya sean archivos o stdin/stdout/stderr), suponiendo que la configuración regional de su entorno se basa en UTF8. Finalmente, para tratar también el código _source_ como UTF8, use el pragma 'use utf8;'. – mklement0

0

Gracias, finalmente obtuvo una solución para no poner UTF-8 :: codificar todo el código. para sintetizar y completa para otros casos, como escribir y leer archivos en UTF-8 y también trabaja con LoadFile de un archivo YAML en UTF8

use utf8; 
use open ':encoding(utf8)'; 
binmode(STDOUT, ":utf8"); 

open(FH, ">test.txt"); 
print FH "something éá"; 

use YAML qw(LoadFile Dump); 
my $PUBS = LoadFile("cache.yaml"); 
my $f = "2917"; 
my $ref = $PUBS->{$f}; 
print "$f \"".$ref->{name}."\" ". $ref->{primary_uri}." "; 

donde caché.yaml es:

--- 
2917: 
    id: 2917 
    name: Semanário 
    primary_uri: 2917.xml 
Cuestiones relacionadas