如何在ActiveState Perl中获取正确的非ASCII命令行参数?

时间:2011-10-19 16:02:57

标签: perl internationalization cmd activestate

运行以下命令

perl -e "for (my $i = 0; $i < length($ARGV[0]); $i++) {print ord(substr($ARGV[0], $i, 1)), qq{\n}; }" αβγδεζ
在具有ActiveState Perl v5.14.2的Windows 7 cmd窗口上的

产生以下结果:

97
223
63
100
101
63

以上值无意义且与任何已知编码不对应,因此尝试使用建议的方法解码它们 How can I treat command-line arguments as UTF-8 in Perl?无济于事。更改命令窗口活动代码页不会更改结果。

4 个答案:

答案 0 :(得分:3)

您的系统与我所知道的每个Windows系统一样,默认使用1252 ANSI代码页,因此您可以尝试使用

use Encode qw( decode );
@ARGV = map { decode('cp1252', $_) } @ARGV;

请注意,cp1252不能代表所有这些字符,这就是控制台和Perl实际接收的原因

  • a 97
  • ß223
  • ? 63
  • d 100
  • e 101
  • ? 63

有一个“宽”接口,用于将(几乎)任何Unicode代码点传递给程序,但

  1. 在提示符下键入命令时,不使用Wide接口。
  2. Perl使用ANSI接口来获取参数,因此即使您使用Wide接口启动Perl,当Perl获取它们时,参数也会降级为ANSI。
  3. 抱歉,这是一种“你不能”的情况。你需要一个不同的方法。 Diomidis Spinellis建议在Win7中更改系统的ANSI代码页:

    1. 控制面板
    2. 地区和语言
    3. 管理
    4. 非Unicode程序的语言
    5. 将非Unicode程序的当前语言设置为与特定字符关联的语言(在您的情况下为希腊语)。
    6. 此时,您将使用与新选择的编码关联的ANSI代码页的编码,而不是cp1252(希腊语为cp1253)。

      use Encode qw( decode );
      @ARGV = map { decode('cp1253', $_) } @ARGV;
      

      请注意,使用chcp修改控制台窗口中使用的代码页不会影响Perl接收其参数的代码页,该参数始终是ANSI代码页。请参阅下面的示例(cp737是希腊语OEM code page,cp1253是希腊语ANSI code page。您可以在this document中找到标记为37和M7的编码。)

      C:\>chcp 737
      Active code page: 737
      
      C:\>echo αβγδεζ | od -t x1
      0000000 98 99 9a 9b 9c 9d 20 0d 0a
      
      C:\>perl -e "print map sprintf('%x ', ord($_)), split(//, $ARGV[0])" αβγδεζ
      e1 e2 e3 e4 e5 e6
      
      C:\>chcp 1253
      Active code page: 1253
      
      C:\>echo αβγδεζ | od -t x1
      0000000 e1 e2 e3 e4 e5 e6 20 0d 0a
      
      C:\>perl -e "print map sprintf('%x ', ord($_)), split(//, $ARGV[0])" αβγδεζ
      e1 e2 e3 e4 e5 e6
      

答案 1 :(得分:0)

这对我有用(在OS-X上,但应该是可移植的):

echo  αβγδεζ |perl -CI -e "chomp($in=<STDIN>);for (my $i = 0; $i < length($in); $i++) {print ord(substr($in, $i, 1)), qq{\n}; }"

那是STDIN;对于ARGV:

perl -CA -e "for (my $i = 0; $i < length($ARGV[0]); $i++) {print ord(substr($ARGV[0], $i, 1)), qq{\n}; }" αβγδεζ

请参阅perlrun中的-C选项:http://perldoc.perl.org/perlrun.html#Command-Switches

答案 2 :(得分:0)

如果我将字符放在一个文件中(来自OS-X),请将其复制到一个Windows框(如file.txt),然后运行:

perl -CI -e "chomp($_=<STDIN>); map{print ord, qq{\n}} split(//)" < file.txt

然后我得到了预期的结果:

946
947
948
949
950

但是,如果我将file.txt的内容复制到命令行,我会感到胡言乱语。

正如@ikegami所说,我不认为可以从命令行执行,因为你没有UTF-8语言环境。

答案 3 :(得分:0)

您可以尝试使用https://metacpan.org/pod/Win32::Unicode::Native。它应该有你需要的东西。