2012-06-20 15 views
6

La causa principal de esta pregunta es mi intento de escribir pruebas para un nuevo módulo de procesamiento de opción/argumento (OptArgs) para Perl. Esto, por supuesto, implica el análisis de @ARGV que estoy haciendo basado en las respuestas a la pregunta this. Esto funciona bien en sistemas donde I18N :: Langinfo :: CODESET está definido [1].En Perl, ¿cómo paso los argumentos Unicode a los comandos externos?

En los sistemas donde langinfo(CODESET) no está disponible Me gustaría al menos hacer un mejor esfuerzo en función del comportamiento observado. Sin embargo, mis pruebas hasta ahora indican que algunos sistemas que no puedo ni siquiera pasan un argumento unicode correctamente a un script externo.

que han logrado ejecutar algo como lo siguiente en varios sistemas en los que "test_script" es un script en Perl que simplemente hace un print Dumper(@ARGV):

use utf8; 
my $utf8 = '¥'; 
my $result = qx/$^X test_script $utf8/; 

Lo que he encontrado es que en FreeBSD el test_script recibe bytes cuales puede decodificarse en el formato interno de Perl. Sin embargo, en OpenBSD y Solaris test_script parece obtener la cadena "\x{fffd}\x{fffd}" que contiene solo el carácter de reemplazo Unicode (¿dos veces?).

No conozco el mecanismo subyacente al operador qx. Supongo que es exec o shells out, pero a diferencia de Filehandles (donde puedo binmodearlos para la codificación) no sé cómo asegurar que haga lo que quiero. Lo mismo con system() para el caso. Entonces mi pregunta es ¿qué estoy haciendo correctamente arriba? De lo contrario, ¿qué es diferente con Perl o el shell o el entorno en OpenBSD y Solaris?

[1] De hecho, creo que hasta ahora solo es Linux según los resultados de los probadores de CPAN.

Update (x2): que actualmente tienen la siguiente correr su camino a través de las configuraciones de cpantester para poner a prueba la hipótesis de Schwern:

use strict; 
use warnings; 
use Data::Dumper; 

BEGIN { 
    if (@ARGV) { 
     require Test::More; 
     Test::More::diag("\npre utf8::all: " 
       . Dumper({ utf8 => $ARGV[0], bytes => $ARGV[1] })); 
    } 
} 

use utf8; 
use utf8::all; 

BEGIN { 
    if (@ARGV) { 
     Test::More::diag("\npost utf8::all: " 
       . Dumper({ utf8 => $ARGV[0], bytes => $ARGV[1] })); 
     exit; 
    } 
} 

use Encode; 
use Test::More; 

my $builder = Test::More->builder; 
binmode $builder->output,   ':encoding(UTF-8)'; 
binmode $builder->failure_output, ':encoding(UTF-8)'; 
binmode $builder->todo_output, ':encoding(UTF-8)'; 

my $utf8 = '¥'; 
my $bytes = encode_utf8($utf8); 

diag("\nPassing: " . Dumper({ utf8 => $utf8, bytes => $bytes, })); 

open(my $fh, '-|', $^X, $0, $utf8, $bytes) || die "open: $!"; 
my $result = join('', <$fh>); 
close $fh; 

ok(1); 
done_testing(); 

Voy a publicar los resultados en varios sistemas cuando vienen a través. Cualquier comentario sobre la validez y/o la corrección de esto sería apreciado. Tenga en cuenta que es no pretende ser una prueba válida. El propósito de lo anterior es poder comparar lo que se recibe en diferentes sistemas.

Resolución: El problema subyacente real resulta ser algo no abordado en mi pregunta ni por la respuesta de Schwern a continuación. Lo que descubrí es que algunas máquinas cpantesters solo tienen una locación ascii instalada/disponible. No debería esperar ningún intento de pasar caracteres UTF-8 a programas en este tipo de entorno para que funcionen. Así que, al final, mi problema fueron las condiciones de prueba no válidas, no el código no válido.

No he visto nada hasta el momento que indique que el operador qx o el módulo utf8::all tienen algún efecto sobre cómo se pasan los parámetros a los programas externos. El componente crítico parece ser el LANG y/o LC_ALL variables de entorno, para informar al programa externo lo que la configuración regional que se están ejecutando en.

Por cierto, mi afirmación original de que mi código está trabajando en todos los sistemas donde I18N :: Langinfo :: CODESET se define como incorrecto.

+0

En una nota relacionada, los BSD parecen estar rotos de otras maneras. Ni siquiera puedo escribir caracteres Unicode a través de una sesión ssh en FreeBSD, lo que da como resultado un comportamiento extraño en el terminal. –

+0

El Unicode-via-ssh probablemente depende en gran medida de qué terminal está utilizando y cuál es su "TERM" en ambos sistemas. – sarnold

+0

No puedo replicar su problema en OS X, pero es posible que desee probar [utf8 :: all] (https://metacpan.org/module/utf8::all) para activar la mayoría de las características de Unicode, incluido Unicode '@ ARGV'. 'qx' también puede verse afectado por el pragma' open', que 'utf8 :: all' usa para hacer que Filehandles respete Unicode. – Schwern

Respuesta

1

qx hace una llamada al shell y puede estar interfiriendo.

Para evitar eso, use utf8::all para encender todo el vudú de Perl Unicode. Luego use la función open para abrir un conducto a su programa, evitando el shell.

use utf8::all; 
my $utf8 = '¥'; 

open my $read_from_script, "-|", "test_script", $utf8; 
print <$read_from_script>,"\n"; 
+0

Evitar el uso del shell con la versión de 3 argumentos de open es una buena sugerencia. Sin embargo, no puedo ver qué efecto se supone que utf8 :: all tiene en los argumentos a la función 'open' ni a la llamada' exec' subyacente. –

+0

Mirando la fuente de utf8 :: all, realmente hace suposiciones sobre la codificación de '@ ARGV' que [esto] (http://stackoverflow.com/questions/2037467/how-can-i-treat-command-line -arguments-as-utf-8-in-perl) advertido contra hacer. Sin embargo, eso se está alejando del tema de esta pregunta. –

+0

@MarkLawrence 'utf8 :: all' está teniendo un efecto a través del pragma' abierto'. Específicamente 'use open ': std" 'parece afectar las aperturas de tubería, probablemente haciendo que STDOUT use UTF-8. Es un buen ejemplo de "deja que alguien más lo resuelva y use su módulo". Y sí, está haciendo una suposición sobre la codificación de '@ ARGV'. Tienes que hacer una suposición, incluso si no asumes ASCII, y UTF-8 es una apuesta bastante segura. Desafortunadamente no es uno que se pueda hacer léxicamente. – Schwern

Cuestiones relacionadas