Поиск слов с поддержкой Unicode — Вопрос

Этот код подходит? Я действительно понятия не имею, какую форму нормализации мне следует использовать (единственное, что я заметил, это то, что с 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};
}

person sid_com    schedule 13.07.2011    source источник
comment
Неважно, какую нормализацию вы используете, если вы используете одну и ту же нормализацию для всех сравниваемых строк!   -  person Kerrek SB    schedule 13.07.2011
comment
@Kerrek Это неправильно. Как Unicode::Collate (и его подкласс U::C::Locale), так и Unicode::GCString специально разработаны таким образом, что нормализация не имеет значения.   -  person tchrist    schedule 16.08.2011


Ответы (1)


Вот это да!! Не могу поверить, что никто не ответил на это. Это супер-пупер отличный вопрос. Вы тоже почти правильно сказали. Мне нравится, что вы используете Unicode::Collate::Locale и Unicode::GCString. Повезло тебе!

Причина, по которой вы получаете «неправильный» вывод, заключается в том, что вы не используете метод columns класса Unicode::GCString для определения ширины печати материала, который вы печатаете.

printf очень глупый и просто считает кодовые точки, а не столбцы, поэтому вам нужно написать свою собственную функцию заполнения, которая учитывает столбцы GCS. Например, чтобы сделать это вручную, вместо того, чтобы писать это:

 printf "%-10.10s", $gstring;

Вы должны написать это:

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

Видишь, как это работает?

Теперь нормализация не имеет значения. Игнорируйте старый комментарий Керрека. Это очень неправильно. UCA специально разработан для того, чтобы не допустить нормализации. Вам придется из кожи вон лезть, чтобы облажаться, например, передав normalization => undef конструктору, если вы хотите использовать его метод gmatch или что-то в этом роде.

person tchrist    schedule 16.08.2011
comment
Но имеет ли значение для подсчета слов ($ hash {key} ++), если я делаю нормализацию перед подсчетом? - person sid_com; 16.08.2011