如何在Perl中将命令行参数视为UTF-8?

如何在Perl中将命令行参数视为UTF-8?,perl,unicode,utf-8,Perl,Unicode,Utf 8,如何在Perl中将@ARGV的元素视为UTF-8 目前我正在使用以下解决方法 use Encode qw(decode encode); my $foo = $ARGV[0]; $foo = decode("utf-8", $foo); 。。它可以工作,但不是很优雅 我使用的是PerlV5.8.8,它是从BashV3.2.25调用的,LANG设置为en_US.UTF-8。您不必对字符串做任何特殊的处理。Perl字符串默认为UTF-8格式,从Perl 5.8开始 perl -CO -le 'p

如何在Perl中将
@ARGV
的元素视为UTF-8

目前我正在使用以下解决方法

use Encode qw(decode encode);

my $foo = $ARGV[0];
$foo = decode("utf-8", $foo);
。。它可以工作,但不是很优雅


我使用的是PerlV5.8.8,它是从BashV3.2.25调用的,LANG设置为en_US.UTF-8。

您不必对字符串做任何特殊的处理。Perl字符串默认为UTF-8格式,从Perl 5.8开始

perl -CO -le 'print "\x{2603}"' | xargs perl -le 'print "I saw @ARGV"'
上面的代码在Ubuntu 9.04、OS X 10.6和FreeBSD 7上运行良好

假乙烯基灌木提出了一个很好的观点,我们可以看到两者之间的明确区别

perl -Mutf8 -wle ';print utf8::is_utf8($ARGV[0]) ? "t" : "f"' a


你这样做似乎是对的。这就是我要做的


但是,这表明命令行标志
-CA
应该告诉它将
@ARGV
视为utf-8。(未经测试)。

外部数据源在Perl中很棘手。对于命令行参数,您可能会将其作为您的区域设置中指定的编码。不要依赖您的区域设置与可能运行您的程序的其他人相同

您必须找出它是什么,然后将其转换为Perl的内部格式。幸运的是,这并不难

模块提供了获取编码所需的内容:

    use I18N::Langinfo qw(langinfo CODESET);
    my $codeset = langinfo(CODESET);
了解编码后,可以将其解码为Perl字符串:

    use Encode qw(decode);
    @ARGV = map { decode $codeset, $_ } @ARGV;
尽管Perl将内部字符串编码为UTF-8,但您不应该想到或知道这一点。您只需解码您得到的任何内容,这会将其转换为Perl的内部表示。相信Perl将处理所有其他事情。当您需要存储数据时,请确保使用您喜欢的编码

如果您知道您的设置是UTF-8,并且终端会将命令行参数作为UTF-8提供给您,那么您可以将
A
选项与Perl的
-C
开关一起使用。这告诉您的程序假定参数编码为UTF-8:

% perl -CA program
只需使用
-C
,就可以实现这一点,这将启用其他几个Unicode选项:

% perl -C program
我发现“如果你知道”是一个很大的危险信号,实际上意味着“我们不确定”。

使用:

这也适用于Win32,对我来说很好。

例如windows 设置代码

在perl中:

use utf8;
use Modern::Perl;
use Encode::Locale qw(decode_argv);

 if (-t)
{
    binmode(STDIN, ":encoding(console_in)");
    binmode(STDOUT, ":encoding(console_out)");
    binmode(STDERR, ":encoding(console_out)");
}

Encode::Locale::decode_argv();
在命令行中

perl -C ppixregexplain.pl qr/\bмама\b/i > ex1.html 2>&1  

其中,尽管命令行参数不是以Perl字符串的形式出现的。它和其他任何东西一样是一个外部数据源。但是如果他或她的shell设置为UTF-8,那么他或她键入的任何东西都将是UTF-8。我发现指定工作环境比覆盖所有可能的环境更容易。现在,如果这意味着要分发给其他人,这会改变情况,但问题是终端将被设置为UTF-8。类似地,大多数情况下,我不会处理
文件::Spec
,即使我的代码在某些系统上无法工作。-CA希望命令行参数编码为UTF-8。这并不意味着他们是。:)谢谢你提供的信息,所以你是说这种方式假设UTF-8编码,但是你的方式去发现编码…?我发现假设任何编码都是不安全的。太多的人让它在他们的机器上工作,然后发现它为其他具有不同设置的人中断。请注意,这在脚本中不起作用,即您不能执行
#/usr/bin/perl-CA
。或者至少我下载的一个脚本失败了。只是一个细微的nit:ARGV本身通常表示名为ARGV的文件句柄。对于@ARGV(保存命令行参数的数组),答案有点不同。:)我这个答案的问题是I18N::Langinfo在Win32上不可用(即使它在corelist中!)。我的perl(5.18.0,Mac OS X 10.8)返回US-ASCII(以$codeset为单位),即使我的终端设置为unicode(UTF-8)。如果我手动将$codeset设置为UTF-8,则decode()会起作用。这将为我在v5.18和X.8中返回
UTF-8
$perl5.18.0-MI18N::Langinfo=Langinfo,code-set-E'say Langinfo(code-set)
。你确定你的设置正确吗?你在哪个版本的perl中找到了
Encode::Locale
?我已经有了v5.10.1版本,尝试
使用Encode::Locale
会导致找不到模块:(它不在core中,您可以在cpan或您的软件包管理器上安装它。
chcp 1251
use utf8;
use Modern::Perl;
use Encode::Locale qw(decode_argv);

 if (-t)
{
    binmode(STDIN, ":encoding(console_in)");
    binmode(STDOUT, ":encoding(console_out)");
    binmode(STDERR, ":encoding(console_out)");
}

Encode::Locale::decode_argv();
perl -C ppixregexplain.pl qr/\bмама\b/i > ex1.html 2>&1