Perl Unicode内部 - 乱用utf8

caj*_*ine 10 unicode perl utf-8

在任何人告诉我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);
}
Run Code Online (Sandbox Code Playgroud)

在这一点上,UTF8编码STDIN我得到了正确的Unicode字符串$data,如"\ W"将与多字节[\p{Alphabetic}\p{Decimal_Number}\p{Letter_Number}](也许更多的东西).那没关系,有效.

据我所知$data没有包含UTF8,但在一个字符串perl's internal Unicode格式.

现在的问题是:

  • 我如何确保(测试它),任何$other_data包含有效的Unicode字符串?
  • 出于什么目的,utf8 :: is_utf8($ data)?整个utf8 pragma对我来说是一个谜.

据我所知,use utf8;只是告诉Perl的,我的源代码是在UTF8的目的(这样做类似的事情时,我的脚本BOM标志开始的-为大尾端) -从Perl的角度来看,我的源代码是类似于外部文件 - 和Perl应该知道它是什么编码...

在上面的例子utf8::is_utf8($data)中将打印好 - 但我不明白为什么.

内部Perl不使用utf8,所以我的utf8数据文件被转换为Perl的内部Unicode,那么为什么utf8::is_utf8($data)返回true $data,不是 utf8格式?或者它被错误命名,该函数应命名为uni :: is_unicode($ data)???

在此先感谢您的澄清.

Ps:@brian d foy - 是的,我还没有有效的Perl编程书 - 我会得到它 - 我保证:) /开玩笑/

ike*_*ami 7

is_utf8 返回有关使用哪种内部存储格式的信息,句点.

  • 它与字符串的值无关(尽管某些字符串只能以两种格式之一存储).
  • 它与字符串是否已被解码无关.
  • 它与字符串是否包含使用UTF-8编码的内容无关.
  • 这不是任何形式的有效性检查.

现在回答你的问题.


整个utf8 pragma对我来说是一个谜.

use utf8;告诉perl您的源代码使用UTF-8编码.如果你不这么说,perl有效地假设它是iso-8859-1(作为内部机制的副作用).

utf8 :: namespace中的函数与pragma无关,它们有多种用途.

  • utf8::encodeutf8::decode:有用的编码和解码功能.类似编码的encode_utf8decode_utf8,但他们就地工作.
  • utf8::upgradeutf8::downgrade:很少使用,但有助于解决XS模块中的错误.更多关于此的信息.
  • utf8::is_utf8:我不知道为什么有人会用它.

我如何确保(测试它),比任何$ other_data包含有效的unicode字符串?

"有效的Unicode字符串"对您意味着什么?Unicode对于不同的情况有不同的有效定义.


出于什么目的,utf8 :: is_utf8($ data)?

调试.它偷看了Perl胆量.


在上面的例子中,utf8 :: is_utf8($ data)将打印OK - 但不明白为什么.

因为NFD碰巧选择返回包含UTF8 = 1格式的字符串的标量.

Perl有两种​​用于存储字符串的格式:

  • UTF8 = 0可以存储一系列8位值.
  • UTF8 = 1可以存储一系列72位值(尽管实际上限制为32位或64位).

第一种格式使用较少的内存,并且在访问字符串中的特定位置时速度更快,但它的内容有限.(例如,它不能存储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
Run Code Online (Sandbox Code Playgroud)

人们通常不必担心这一点,但有错误的模块.尽管如此,Perl甚至还有一些错误的角落use feature qw( unicode_strings );.可以使用utf8::upgradeutf8::downgrade将标量的格式更改为XS函数所期望的格式.


或者它命名错误,函数应命名为uni :: is_unicode($ data)???

那不是更好.Perl无法知道字符串是否是Unicode字符串.如果您需要跟踪它,您需要自己跟踪它.

UTF8 = 0格式的字符串可能包含Unicode代码点.

my $s = "abc";  # U+0041,0042,0043
Run Code Online (Sandbox Code Playgroud)

UTF8 = 1格式的字符串可能包含非Unicode代码点的值.

my $s = pack('W*', @temperature_measurements);
Run Code Online (Sandbox Code Playgroud)


dax*_*xim 6

我如何确保(测试它),比任何$ other_data包含有效的unicode字符串?

事后不能确定字符串是否具有字符语义或字节语义.Perl不会为您跟踪此信息.您必须通过仔细编程来跟踪它:在边界处进行编码和解码; 用于字节语义的:raw ,:encoding(foo)用于字符语义.使用变量和函数的命名约定来清楚地区分语义并使错误的代码看起来错误.

出于什么目的,utf8 :: is_utf8($ data)?

它告诉你SvUTF8旗帜的存在,仅此而已.对于大多数开发人员来说,这几乎完全没用,因为它是一个内部的东西.该标志并不意味着字符串具有字符语义,它的缺失并不意味着字符串具有字节语义.

整个utf8 pragma对我来说是一个谜.

可能是因为它过度记录,因此令人困惑.大多数开发人员可以在声明其目的是在源代码中启用Unicode文字的部分之后停止阅读.

在上面的例子中,utf8 :: is_utf8($ data)将打印OK - 但不明白为什么.

因为uni :: perl能够实现use open qw(:utf8 :std);.从STDIN读取的任何输入<>都将被解码.之后的归一化步骤不会改变这一点.