在任何人告诉我RTFM之前,我必须说 - 我已经深入了解:
所以,基本代码:
use 5.014; #getting 'unicode_strings' feature
use uni::perl; #turning on many utf8 things
use Unicode::Normalize qw(NFD NFC);
use warnings;
while(<>) {
chomp;
my $data = NFD($_);
say "OK" if utf8::is_utf8($data);
}
此时,来自 utf8 编码的STDIN我在$data
中得到了一个正确的 unicode 字符串,例如“\ w”将匹配多字节[\p{Alphabetic}\p{Decimal_Number}\p{Letter_Number}]
(可能更多)。那没关系,而且很有效。
AFAIK $data
不包含utf8,但是perl's internal Unicode
格式的字符串。
现在问题:
$other_data
包含有效的Unicode字符串?我理解use utf8;
只是为了告诉Perl我的源代码是在utf8中(所以做类似的事情,就像我的脚本以BOM标志开始 - 对于BigEndian) - 从Perl的角度来看,我的源代码就像一个外部文件 - 而Perl应该知道它是什么编码......
在上面的示例中,utf8::is_utf8($data)
将打印正常 - 但我不明白为什么。
内部Perl不使用utf8,因此我的utf8数据文件被转换为Perl的内部Unicode,为什么utf8::is_utf8($data)
对$data
返回true,而不是以utf8格式?或者它被错误命名,该函数应命名为uni :: is_unicode($ data)???
提前感谢您的澄清。
Ps:@brian d foy - 是的,我还没有 Effective Perl Programming 书 - 我会得到它 - 我保证:) /开玩笑/
答案 0 :(得分:7)
is_utf8
返回有关使用了哪种内部存储格式的信息,周期。
现在回答你的问题。
整个utf8编译指示对我来说是一个谜。
use utf8;
告诉perl
您的源代码是使用UTF-8编码的。如果你不这么说,perl
有效地假定它是iso-8859-1(作为内部机制的副作用)。
utf8 :: namespace中的函数与pragma无关,它们有多种用途。
utf8::encode
和utf8::decode
:有用的编码和解码功能。与Encode的encode_utf8
和decode_utf8
类似,但它们可以就地生效。utf8::upgrade
和utf8::downgrade
:很少使用,但对于解决XS模块中的错误非常有用。更多内容如下。utf8::is_utf8
:我不知道为什么会有人使用它。我如何确保(测试它),比任何$ other_data包含有效的unicode字符串?
&#34;有效的Unicode字符串&#34;对你意味着什么? Unicode对于不同的情况有不同的有效定义。
出于什么目的是utf8 :: is_utf8($ data)?
调试。它偷看了Perl胆量。
在上面的示例中,utf8 :: is_utf8($ data)将打印正常 - 但不明白为什么。
因为NFD碰巧选择返回包含UTF8 = 1格式字符串的标量。
Perl有两种用于存储字符串的格式:
第一种格式使用更少的内存,并且在访问字符串中的特定位置时速度更快,但它可以包含的内容有限。 (例如,它不能存储Unicode代码点,因为它们需要21位。)Perl可以在两者之间自由切换。
use utf8;
use feature qw( say );
my $d = my $u = "abcdé";
utf8::downgrade($d); # Switch to using the UTF8=0 format for $d.
utf8::upgrade($u); # Switch to using the UTF8=1 format for $u.
say utf8::is_utf8($d) ?1:0; # 0
say utf8::is_utf8($u) ?1:0; # 1
say $d eq $u ?1:0; # 1
人们通常不必担心这一点,但有一些错误的模块。尽管有use feature qw( unicode_strings );
,但Perl甚至还有错误的角落。可以使用utf8::upgrade
和utf8::downgrade
将标量的格式更改为XS函数所期望的格式。
或者它命名错误,函数应命名为uni :: is_unicode($ data)???
那没有好转。 Perl无法知道字符串是否是Unicode字符串。如果您需要跟踪它,您需要自己跟踪它。
UTF8 = 0格式的字符串可能包含Unicode代码点。
my $s = "abc"; # U+0041,0042,0043
UTF8 = 1格式的字符串可能包含不是Unicode代码点的值。
my $s = pack('W*', @temperature_measurements);
答案 1 :(得分:6)
我如何确保(测试它),而不是任何$ other_data包含有效的unicode字符串?
您无法确定事后是否字符串具有字符语义或字节语义。 Perl不会为您跟踪此信息。您必须通过仔细编程来跟踪它:在边界处进行编码和解码; :raw
layer用于字节语义,:encoding(foo)
用于字符语义。使用naming conventions获取变量和函数,以清楚地区分语义并使错误的代码看起来错误。
出于什么目的,utf8 :: is_utf8($ data)?
它告诉你SvUTF8
标志的存在,仅此而已。对于大多数开发人员来说,这几乎完全没用,因为它是一个内部的东西。该标志并不意味着字符串具有字符语义,它的缺失并不意味着字符串具有字节语义。
整个utf8 pragma对我来说都是一个谜。
可能是因为它过度记录,因此令人困惑。大多数开发人员可以在声明其目的是在源代码中启用Unicode文字的部分之后停止阅读。
在上面的示例中,utf8 :: is_utf8($ data)将打印正常 - 但不明白为什么。
因为uni :: perl启用了use open qw(:utf8 :std);
。从STDIN读取的任何带有<>
的输入都将被解码。之后的归一化步骤不会改变它。