4

我正在处理 Perl 中以 utf-8 编码的字符串。一个任务是我需要一种方法来知道以带有变音符号的字母开头的单词,例如“écrit”,以与“elephant”相同的字母开头,以及“England”。我需要一个通用的解决方案,因为我将使用多种语言。我需要知道这一点,因为我正在为索引创建字母标题。我刚才提到的每个单词都将存储在“E”下。

有没有一种简单的方法可以做到这一点?

4

3 回答 3

3

Text::Unidecode可以帮助你。它将 Unicode 转换为 ASCII。

$ perl -Mutf8 -e 'use Text::Unidecode; print unidecode("écrit")'
ecrit
于 2013-02-21T17:37:49.923 回答
2

字符串的相等性和顺序由称为排序规则的事物决定。棘手的部分是它们取决于语言和文化(技术术语是“语言环境”)。例如,您可能认为 ø 和 o 等价,但对于丹麦人来说,它们是不同的字母,并且必须以不同的方式排序。

使用排序规则的 Perl 模块是Unicode::Collate.

更新:您还可以使用 Perl 的内置语言环境支持use locale

use locale; 
use POSIX qw(setlocale LC_ALL);

setlocale(LC_ALL, ''); # Set default locale from environment variables

这使得内置函数例如sortcmp使用语言环境的规则来排序字符串。但小心点; 更改程序的语言环境可能会产生意想不到的后果,例如将输出中的小数点更改为逗号printf

更新 2: POSIX 语言环境显然以各种方式被破坏。你最好使用Unicode::Collateand Unicode::Collate::Locale

于 2013-02-22T16:07:26.880 回答
1

我假设您是按英文排序规则排序并且有字母文本。下面的代码是一个好的开始,但现实世界比这更复杂。(例如,中文文本根据上下文有不同的词典规则,例如通用词典,卡拉OK歌曲列表,电子门铃名单,......)我无法提供完美的解决方案,因为问题的信息太少了。

use 5.010;
use utf8;
use Unicode::Collate::Locale 0.96;
use Unicode::Normalize qw(normalize);

my $c = Unicode::Collate::Locale->new(locale => 'en');
say for $c->sort(qw(
    eye
    egg
    estate
    etc.
    eleven
    e.g.
    England
    ensure
    educate
    each
    equipment
    elephant
    ex-
    ending
    écrit
));
say '-' x 40;
for my $word (qw(écrit Ëmëhntëhtt-Rê Ênio ècole Ēadƿeard Ėmma Ędward Ẽfini)) {
    say sprintf '%s should be stored under the heading %s',
        $word, ucfirst substr normalize('D', $word), 0, 1;
}

__END__
each
écrit
educate
e.g.
egg
elephant
eleven
ending
England
ensure
equipment
estate
etc.
ex-
eye
----------------------------------------
écrit should be stored under the heading E
Ëmëhntëhtt-Rê should be stored under the heading E
Ênio should be stored under the heading E
ècole should be stored under the heading E
Ēadƿeard should be stored under the heading E
Ėmma should be stored under the heading E
Ędward should be stored under the heading E
Ẽfini should be stored under the heading E
于 2013-02-24T16:50:44.620 回答