perl - 在 Perl 中,如何将 unicode 参数传递给外部命令?

标签 perl unicode utf-8 solaris openbsd

这个问题的根本原因是我尝试为 Perl 的新选项/参数处理模块 ( OptArgs ) 编写测试。这当然涉及解析 @ARGV我正在根据对 this 的答案进行操作问题。这在定义了 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 背后的机制运算符(operator)。我猜是exec 's 或 shells,但与文件句柄不同(我可以对它们进行 binmode 编码),我不知道如何确保它符合我的要求。与 system() 相同对于这个问题。所以我的问题是我在上面做错了什么?否则 Perl 或 shell 或 OpenBSD 和 Solaris 上的环境有什么不同?

[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 的所有系统上工作是不正确的。

最佳答案

qx调用外壳,它可能会干扰。

为避免这种情况,请使用 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";

关于perl - 在 Perl 中,如何将 unicode 参数传递给外部命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11111735/

相关文章:

java - 为什么我的程序不能正确处理字符编码?

java - 如何确定字符串是否包含无效的编码字符

mysql - 如何检查二进制字符串是否为 mysql 中的 UTF-8?

Python:将utf-8字符串转换为字节字符串

php - 计算各种语言单词的 PHP 库/类?

perl - 如何实现不涉及加载到内存的对象持久化?

perl - 输出 4 个随机单词的最短 Peel 解决方案

perl - 强制 Perl Dancer 使用 HTTP/1.1

perl - 如何在 Perl 列表中找到值的数量?

python - 语法错误 : Non-ASCII character '\xa3' in file when function returns '£'