此问题的根本原因是我尝试为Perl编写新选项/参数处理模块(OptArgs)的测试。这当然涉及根据this问题的答案解析我正在做的@ARGV
。这适用于定义了I18N :: Langinfo :: CODESET的系统[1]。
在langinfo(CODESET)
不可用的系统上,我希望至少根据观察到的行为尽最大努力。但是到目前为止我的测试表明,有些系统我甚至无法正确地将 unicode参数传递给外部脚本。
我设法在各种系统上运行类似下面的内容,其中“test_script”是仅执行print Dumper(@ARGV)
的Perl脚本:
use utf8;
my $utf8 = '¥';
my $result = qx/$^X test_script $utf8/;
我发现在FreeBSD上,test_script接收可以解码为Perl内部格式的字节。但是在OpenBSD和Solaris上,test_script似乎得到的字符串"\x{fffd}\x{fffd}"
只包含unicode替换字符(两次?)。
我不知道qx
运算符背后的机制。我认为它要么是exec
,要么是shell,但不像文件句柄(我可以将它们用于编码的binmode)我不知道如何确保它做我想要的。与system()
相同。所以我的问题是我上面没有正确做什么?否则与Perl或OpenBSD和Solaris上的shell或环境有什么不同?
[1]实际上我认为到目前为止根据CPAN测试人员的结果只有Linux。
更新(x2):我目前通过cpantester的设置运行以下方法来测试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();
我会在各种系统上发布结果。任何关于此的有效性和正确性的评论都会受到赞赏。请注意,不旨在成为有效的测试。上述目的是能够比较不同系统上收到的内容。
决议:真正的潜在问题在我的问题中未得到解决,Schwern的答案也未在下面解决。我发现一些cpantesters机器只安装了/可用的ascii语言环境。我不应该期望任何尝试将UTF-8字符传递给此类环境中的程序才能工作。所以最后我的问题是无效的测试条件,而不是无效的代码。
到目前为止,我没有看到任何内容表明qx
运算符或utf8::all
模块对参数传递给外部程序的方式有任何影响。关键组件似乎是LANG
和/或LC_ALL
环境变量,用于通知外部程序它们正在运行的语言环境。
顺便说一下,我的原始断言是我的代码在所有定义了I18N :: Langinfo :: CODESET的系统上运行是不正确的。
答案 0 :(得分:2)
qx
调用shell,可能会干扰。
为避免这种情况,请使用utf8::all打开所有Perl Unicode voodoo。然后使用open
函数打开程序的管道,避免使用shell。
use utf8::all;
my $utf8 = '¥';
open my $read_from_script, "-|", "test_script", $utf8;
print <$read_from_script>,"\n";