Perl的Unicode的内部 - 惹UTF8(Perl Unicode internals - m

2019-07-29 15:35发布

之前有人会告诉我RTFM,我必须说 - 我已经挖通:

  • 为什么现代的Perl避免默认UTF-8?
  • 核对表用Perl去Unicode的方式
  • 如何匹配字符串在Perl读音符号?
  • 如何使“使用我的默认::”与现代的Perl和UTF8默认值?
  • 和其他许多人(如perluniintro等) -但是- 当然 ,错过了什么

因此,基本的代码:

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我得到了一个正确的unicode字符串$data ,如“\ W”将与多字节[\p{Alphabetic}\p{Decimal_Number}\p{Letter_Number}]也许更多的东西)。 这是确定和作品。

AFAIK $data 包含UTF8,但在一个字符串perl's internal Unicode格式。

现在的问题:

  • 我怎么能保证(测试),任何$other_data包含有效的Unicode字符串?
  • 出于什么目的是UTF8 :: is_utf8($数据)? 整个UTF8附注是对我来说是一个谜。

据我所知, 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($数据)???

在此先感谢澄清。

PS:d @布赖恩富瓦-是的,我还没有有效的Perl编程的书-我会得到它-我保证:) /开玩笑/

Answer 1:

is_utf8返回关于其中使用内部存储格式信息,期限。

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

现在到你的问题。


整个UTF8附注是对我来说是一个谜。

use utf8; 告诉perl源代码是使用UTF-8编码。 如果你不告诉它的话, perl有效假定它是ISO-8859-1(作为内部机制的副作用)。

在UTF8 ::命名空间中的功能无关的编译,他们有多种用途的。

  • utf8::encodeutf8::decode :有用的编码和解码的功能。 编码的类似encode_utf8decode_utf8 ,但他们就地工作。
  • utf8::upgradeutf8::downgrade :很少使用,但对于XS模块周围的错误时非常有用。 更多关于这下面。
  • utf8::is_utf8 :我不知道为什么会有人曾经使用。

我怎么能保证(测试),比任何$ other_data包含有效的Unicode字符串?

什么是“有效的Unicode字符串”对你意味着什么? Unicode有针对不同情况的有效的定义不同。


出于什么目的是UTF8 :: is_utf8($数据)?

调试。 它在偷窥Perl的胆量。


在上面的例子UTF8 :: is_utf8($数据)将打印好的 - 但不明白为什么。

因为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

人们通常不必担心这个问题,但也有越野车的模块。 还有,尽管剩余的Perl甚至马车的角落use feature qw( unicode_strings ); 。 我们可以使用utf8::upgradeutf8::downgrade改变一个标量由XS函数预期的格式。


或者是误命名和功能应该被命名为UNI :: is_unicode($数据)???

这是再好不过的。 Perl有没有办法知道一个字符串是否是一个Unicode字符串或没有。 如果你需要跟踪这一点,你需要亲自跟踪它。

在UTF8 = 0格式串可以包含Unicode代码点。

my $s = "abc";  # U+0041,0042,0043

在UTF8 = 1种格式串可以包含不Unicode代码点的值。

my $s = pack('W*', @temperature_measurements);


Answer 2:

我怎么能保证(测试),比任何$ other_data包含有效的Unicode字符串?

你不能确定事后字符串是否具有字符语义或字节语义。 Perl并不为你追踪这一点。 你必须小心编程跟踪它:在边界编码和解码; :raw 层为字节语义, :encoding(foo)为字符语义。 采用命名约定的变量和函数的语义之间有明显的区别,并作出错误的代码看起来是错误的。

出于什么目的是UTF8 :: is_utf8($数据)?

它告诉你的存在SvUTF8标志,仅此而已。 这是大多数开发商几乎完全无用的,因为它是一个内部的事情。 该标志并不意味着字符串具有字符语义,它的缺失并不意味着字符串具有字节语义。

整个UTF8附注是对我来说是一个谜。

可能是因为是overdocumented,因此混乱。 大多数开发人员可以在那里是说,它的目的是使在源代码中的Unicode文本的部分后停止阅读。

在上面的例子UTF8 :: is_utf8($数据)将打印好的 - 但不明白为什么。

因为单向:: perl的这使得能够use open qw(:utf8 :std); 。 从STDIN与读取的任何输入<>将被解码。 标准化步骤之后不改变。



文章来源: Perl Unicode internals - mess with utf8