10

在有人告诉我 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 我得到了一个正确的unicode字符串$data,例如“\w”将匹配多字节[\p{Alphabetic}\p{Decimal_Number}\p{Letter_Number}](可能更多)。没关系并且有效。

AFAIK$data不包含 utf8,而是格式的字符串perl's internal Unicode

现在的问题:

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

我知道这use utf8;只是为了告诉 Perl 我的源代码在 utf8 中(所以当我的脚本以 BOM 标志开头时做类似的事情 - 对于 BigEndian) - 从 Perl 的角度来看,我的源代码就像一个外部文件 - Perl 应该知道它是什么编码......

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

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

提前感谢您的澄清。

Ps:@brian d foy - 是的,我仍然没有有效的 Perl 编程书 - 我会得到它 - 我保证 :) /joking/

4

2 回答 2

7

is_utf8返回有关使用哪种内部存储格式的信息,期间。

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

现在回答你的问题。


整个 utf8 pragma 对我来说是个谜。

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

utf8:: 命名空间中的函数与 pragma 无关,它们有多种用途。

  • utf8::encodeutf8::decode:有用的编码和解码功能。类似于 Encode 的encode_utf8and decode_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

通常不必担心这一点,但是有错误的模块。尽管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

UTF8=1 格式的字符串可能包含不是 Unicode 代码点的值。

my $s = pack('W*', @temperature_measurements);
于 2012-05-30T21:28:27.900 回答
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 读取的任何输入<>都将被解码。之后的标准化步骤不会改变这一点。

于 2012-05-30T21:43:21.353 回答