Perl字符串内部

n0r*_*0rd 8 string perl encoding

perl字符串如何在内部表示?使用什么编码?如何正确处理不同的编码?

我已经使用perl很长一段时间了,但它不包括很多字符串处理在不同的编码,当我遇到一个与编码有关的小问题时,我通常采取一些萨满行动.

直到这一刻我才将perl字符串视为字节序列,这对我的任务非常适合.现在我需要对UTF-8编码文件进行一些处理,这里就麻烦了.

首先,我将文件读入字符串,如下所示:

open(my $in, '<', $ARGV[0]) or die "cannot open file $ARGV[0] for reading";
binmode($in, ':utf8');

my $contents;

{
    local $/;
    $contents = <$in>;
}

close($in);
Run Code Online (Sandbox Code Playgroud)

然后只需打印它:

print $contents;
Run Code Online (Sandbox Code Playgroud)

我得到两件事:警告Wide character in print at <scriptname> line <n>和控制台中的垃圾.所以我可以得出结论,perl字符串有一个"字符"的概念,可以是"宽"或不是,但是当打印时,这些"宽"字符在控制台中表示为多个字节,而不是单个"字符".(我现在想知道为什么我以前使用二进制文件的所有经验都非常适合我预期它在没有任何"字符"问题的情况下工作的方式).

为什么然后我在控制台看到垃圾?如果perl在某些已知编码中将字符串存储为字符,我认为找到控制台编码和正确打印文本并不是一个大问题.(我使用Windows,BTW).

如果perl将字符串存储为可变宽度字符序列(例如,使用相同的UTF-8编码),为什么这样做?从我的C经验来看,处理字符串是PAIN.

更新.

我使用两台计算机进行测试,一台运行安装了英语语言包的Windows 7 x64,但使用ActivePerl 5.10.1 x64进行俄语区域设置(因此我将cp866作为OEM代码页,cp1251作为ANSI); 另一个运行Windows XP 32位俄语本地化与Cygwin Perl 5.10.0.

感谢链接,现在我对正在发生的事情以及应该如何完成工作有了更深刻的理解.

dyl*_*lan 4

在读取文件之前设置 utf8 是好的,它会自动将字节解码为内部编码。(这也是 UTF-8,但您不需要知道,也不应该依赖。)

在打印之前,您需要将字符编码回字节。

use Encode;  
utf8::encode($contents);
Run Code Online (Sandbox Code Playgroud)

对于除 unicode 之外的其他编码,还有一个包含两个参数的编码形式。(这句话太重复了不是吗?)

这是一个很好的参考。(本来应该更多,但这是我的第一篇文章。)也请查看 perlunitut,以及 Joel on Software 上的 unicode 文章。

http://www.ahinea.com/en/tech/perl-unicode-struggle.html

哦,它必须使用多字节字符串,否则它就不是 unicode。

  • 不要使用“utf8”包中的函数。文档说:**除了告诉 Perl 您的脚本是用 UTF-8 编写的之外,不要将此编译指示用于任何其他用途。**而是始终使用“Encode”模块。 (3认同)
  • 您已指定输入编码。你做你的事。然后指定输出编码。我认为我提到的文章解释得更好。 (2认同)