控制台(@ARGV)/Windows对Perl-unicode的支持/

控制台(@ARGV)/Windows对Perl-unicode的支持/,perl,unicode,argv,Perl,Unicode,Argv,我试图在perl脚本中获取unicode字符作为参数: C:\>perl test.pl ö #---- # test.pl #---- #!/usr/bin/perl use warnings; use strict; my ($name, $number) = @ARGV; if (not defined $name) { die "Need name\n"; } if (defined $number) { print "Save '$name' and '$

我试图在perl脚本中获取unicode字符作为参数:

C:\>perl test.pl ö

#----
# test.pl
#----
#!/usr/bin/perl
use warnings;
use strict;

my ($name, $number) = @ARGV;

if (not defined $name) {
    die "Need name\n";
}

if (defined $number) {
    print "Save '$name' and '$number'\n";
    # save name/number in database
    exit;
}

if ($name eq 'ö') {
    print "Fetch umlaut 'oe'\n";
} elsif ($name eq 'o') {
    print "Fetch simple 'o'\n";
} else {
    print "Fetch other '$name'\n";
}

print "ü";
我得到了输出:

Fetch simple 'o'
ü
我已经在Python3中测试了代码(算法),它可以工作,所以我得到了“ö”。 但显然,在perl中,我必须添加或设置更多内容。 不管是草莓Perl还是ActiveState Perl。我得到了同样的结果

提前谢谢

#!/usr/bin/perl

use strict;
use warnings;

my $encoding_in;
my $encoding_out;
my $encoding_sys;
BEGIN {
    require Win32;

    $encoding_in  = 'cp' . Win32::GetConsoleCP();
    $encoding_out = 'cp' . Win32::GetConsoleOutputCP();
    $encoding_sys = 'cp' . Win32::GetACP();

    binmode(STDIN,  ":encoding($encoding_in)");
    binmode(STDOUT, ":encoding($encoding_out)");
    binmode(STDERR, ":encoding($encoding_out)");
}

use Encode qw( decode );

{
    my ($name, $number) = map { decode($encoding_sys, $_) } @ARGV;

    if (not defined $name) {
        die "Need name\n";
    }

    if (defined $number) {
        print "Save '$name' and '$number'\n";
        # save name/number in database
        exit;
    }

    if ($name eq 'ö') {
        print "Fetch umlaut 'oe'\n";
    } elsif ($name eq 'o') {
        print "Fetch simple 'o'\n";
    } else {
        print "Fetch other '$name'\n";
    }

    print "ü";
}

另外,您应该添加
使用功能qw(unicode_字符串)和/或使用UTF-8对文件进行编码,并添加
使用utf8

除了ikagami的回答之外,我还是
Encode::Locale
模块的粉丝,该模块可以自动为当前控制台的代码页创建别名。它可以很好地与Win32、OS X和其他风格的*nix配合使用

#!/usr/bin/perl

use strict;
use warnings;

# These two lines make life better when you leave the world of ASCII
# Just remember to *save* the file as UTF8....
use utf8;
use feature 'unicode_strings';

use Encode::Locale 'decode_argv';         # We'll use the console_in & console_out aliases as well as decode_argv().
use Encode;

binmode(STDIN,  ":encoding(console_in)");
binmode(STDOUT, ":encoding(console_out)");
binmode(STDERR, ":encoding(console_out)");

decode_argv( );   # Decode ARGV in place
my ($name, $number) = @ARGV;

if (not defined $name) {
    die "Need name\n";
}

if (defined $number) {
    print "Save '$name' and '$number'\n";
    # save name/number in database
    exit;
}

if ($name eq 'ö') {
    print "Fetch umlaut 'oe'\n";
} elsif ($name eq 'o') {
    print "Fetch simple 'o'\n";
} else {
    print "Fetch other '$name'\n";
}

print "ü";

也许这只是语法上的甜点,但它便于阅读并促进跨平台兼容性。

我认为这个问题的代码答案很有针对性,但并不完整:

  • 这样,构建一个包含所有代码页+源代码编码的脚本非常复杂,而且更难使其可移植:ö可能为拉丁字母用户所知,但也存在

  • 它们可以在特定代码页中使用字符正常运行,但如果字符不在其中,它们将失败(注释中的某些用户可能就是这种情况)。请注意

  • 根本的问题是,Perl 5 for Windows并非按照Windows的理解使用Unicode支持编译:它只是linux代码的一个端口,因此,几乎所有Unicode字符在到达Perl代码之前都已损坏

A.Sinan联合国大学的网页(下)提供了一个较长的技术解释(和一个C补丁!)

因此(但不是精神萎靡者):在Windows中重新编译perl.exe是可能的,并且几乎完全符合Unicode。希望有一天它们会集成到源代码中。。。直到他们回来


还请注意,需要一个具有完全Unicode支持的适当命令控制台。一个快速的解决方案是使用Windows'cmd.exe。

我不知道这是否是针对每个场景的解决方案,但我可以在调用脚本时使用参数“-CAS”来避开

例如:

脚本1:

use strict;
use utf8;

$|++; # Prevent buffering issues


my ($arg) = @ARGV;
save_to_file('test.txt', $arg);

sub save_to_file{   

    my ($filename, $content) = @_;

    open(my $fh, '>:encoding(UTF-8)', $filename) or die "Can't open < $filename: $!";;
    print $fh $content;
    close $fh;

    return;
}

您对
Encode::Locale
有何看法?它似乎取代了您已有的一些代码行。@tjd,看起来您确实可以使用它。请随意发布一个答案,我将投票,甚至可能删除我的!它不起作用。我只得到一个简单的'o',显然它会自动解析为'o'。这是为MSWin32-x64-multi-thread构建的perl 5,版本24,subversion 0(v5.24.0)。这已经过测试。您能提供程序填充的编码变量的值吗?@ikegami我可以更改编码,但sys编码保持不变。编码输入:cp866编码输出:cp866编码系统:cp1251或编码输入:cp65001编码输出:cp65001编码系统:cp1251未定义子例程&main::decode_argv在vidCmpr2.pl第18行调用。@Banish您是对的。我忘了在使用行中导入那个符号。谢谢你的提醒。是的,我必须进口包裹。现在它编译成功了,但仅此而已。我已经通过更改控制台代码页(chcp1252)或者甚至使用perl6对其进行了测试。它将“ö”解析为简单的“o”。Python和java解析它没有问题。PS:对不起。我错了。它只适用于python。它在java上不起作用。@最后一步是确保要比较的字符串的格式相同(规范化)。
use strict;
use utf8;


execute_command();

sub execute_command {


    my $command = "perl -CAS simple_utf_string.pl äääöööü";

    # Execute command
    print "The command to run is: $command\n";
    open my $command_pipe, "-|:encoding(UTF-8)", $command or die "Pipe from $command failed: $!";
    while (<$command_pipe>) {
        print  $_;
    }
}
äääöööü