4

这段代码可以吗?我真的不知道我应该使用哪种规范化形式(我唯一注意到的是NFD我得到了错误的输出)。

#!/usr/local/bin/perl
use warnings;
use 5.014;
use utf8;
binmode STDOUT, ':encoding(utf-8)';

use Unicode::Normalize;
use Unicode::Collate::Locale;
use Unicode::GCString;

my $text = "my taxt täxt";
my %hash;

while ( $text =~ m/(\p{Alphabetic}+(?:'\p{Alphabetic}+)?)/g ) { #'
    my $word = $1;
    my $NFC_word = NFC( $word );
    $hash{$NFC_word}++;
}

my $collator = Unicode::Collate::Locale->new( locale => 'DE' ); 

for my $word ( $collator->sort( keys %hash ) ) {
    my $gcword = Unicode::GCString->new( $word );
    printf "%-10.10s : %5d\n", $gcword, $hash{$word};
}
4

1 回答 1

3

哇!!我不敢相信没有人回答这个问题。这是一个非常棒的问题。你也几乎做对了。我喜欢你使用 Unicode::Collat​​e::Locale 和 Unicode::GCString。对你有益!

你得到“错误”输出的原因是你没有使用 Unicode::GCString 类的columns方法来确定你正在打印的东西的打印宽度。

printf非常愚蠢,只计算代码点,而不是列,因此您必须编写自己的填充函数,将 GCS 列考虑在内。例如,手动完成,而不是这样写:

 printf "%-10.10s", $gstring;

你必须这样写:

 $colwidth = $gcstring->columns();
 if ($colwidth > 10) {
      print $gcstring->substr(0,10);
 } else {
     print " " x (10 - $colwidth);
     print $gcstring;
 }

看看它是如何工作的?

现在标准化并不重要。忽略 Kerrek 的旧评论。这是非常错误的。UCA 专门设计为不让规范化进入问题。您必须向后弯腰才能搞砸,例如通过传递normalization => undef给构造函数以防万一您想使用它的gmatch方法或类似的方法。

于 2011-08-16T01:51:41.103 回答