我有一个外部模块,它会给我一些字符串。我不确定字符串是如何返回的。我真的不知道,Unicode字符串是如何工作的以及原因。
模块应该返回,例如捷克语“být”,意思是“将来”。 (如果你看不到第二个字母 - 它应该看起来像this。)如果我显示模块返回的字符串,使用数据转储器,我将其视为b\x{fd}t
。
但是,如果我尝试用print $s
打印它,我会收到“打印宽字符”警告,并且?而不是ý。
如果我尝试Encode::decode(whatever, $s);
,无论如何都无法打印生成的字符串(总是带有“宽字符”警告,有时带有错位的字符,有时正确),无论我放在whatever
中。
如果我尝试Encode::encode("utf-8", $s);
,可以打印生成的字符串而不会出现问题或错误消息。
如果我使用use encoding 'utf8';
,则无需编码/解码即可进行打印。 然而,如果我使用IO::CaptureOutput
或Capture::Tiny
模块,它会再次开始喊“宽字符”。
我有几个问题,主要是关于究竟发生了什么。 (我试着阅读perldocs,但我对他们并不是很明智)
use encoding
做了什么?为什么默认编码与utf-8
不同?编辑:有人告诉我使用-C
或binmode
或PERL_UNICODE
。这是一个很好的建议。然而,不知何故,两个捕获模块都神奇地破坏了STDOUT的UTF8-ness。这似乎是模块的一个错误,但我不太确定。
edit2:好的,最好的解决方案是转储模块并自己编写“捕获”(灵活性更低)。
答案 0 :(得分:5)
decode
函数将假定为ENCODING的字节序列解码为Perl的内部形式(utf8)。您的输入似乎已经解码,encode()
函数将Perl内部表单中的字符串编码为ENCODING。encoding
编译指示允许您以您喜欢的任何编码编写脚本。字符串文字自动转换为perl的内部形式。另见perluniintro,perlunicode,Encode module,binmode()函数。
答案 1 :(得分:3)
我建议阅读我的书 Effective Perl Programming 中的Unicode章节。我们将所有可以找到的文档放在一起,并在Perl中解释Unicode比我在其他任何地方看到的更加连贯。
这个程序对我来说很好用:
#!perl
use utf8;
use 5.010;
binmode STDOUT, ':utf8';
my $string = return_string();
say $string;
sub return_string { 'být' }
此外,Capture::Tiny对我来说还不错:
#!perl
use utf8;
use 5.010;
use Capture::Tiny qw(capture);
binmode STDOUT, ':utf8';
my( $stdout, $stderr ) = capture {
system( $^X, '/Users/brian/Desktop/czech.pl' );
};
say "STDOUT is [$stdout]";
IO::CaptureOutput似乎有一些问题:
#!perl
use utf8;
use 5.010;
use IO::CaptureOutput qw(capture);
binmode STDOUT, ':utf8';
capture {
system( $^X, '/Users/brian/Desktop/czech.pl' );
} \my $stdout, \my $stderr;
say "STDOUT is [$stdout]";
为此,我得到:
STDOUT is [být
]
然而,这很容易解决。不要使用该模块。 :)
答案 2 :(得分:1)
您还应该查看PERL_UNICODE
environment variable,这与使用the -C
option相同。这允许您将STDIN / STDOUT / STDERR(和@ARGV
)设置为UTF-8,而无需更改脚本。