我在Perl中处理以utf-8编码的字符串。一个任务是我需要一种方法来知道以带有变音符号的字母开头的单词,例如“écrit”,以与“elephant”相同的字母开头,以及“England”。我需要一个通用的解决方案,因为我将使用多种语言。我需要知道这一点,因为我正在为索引创建字母标题。我刚提到的每个单词都存储在“E”下。
有直接的方法吗?
答案 0 :(得分:3)
Text::Unidecode可以帮到你。它将Unicode转换为ASCII。
$ perl -Mutf8 -e 'use Text::Unidecode; print unidecode("écrit")'
ecrit
答案 1 :(得分:2)
字符串的平等和顺序由称为排序规则的东西决定。棘手的部分是它们依赖于语言和文化(技术术语是“语言环境”)。例如,你可以考虑ø和o等价物,但对于丹麦人来说,它们是不同的字母,必须以不同的方式订购。
用于处理归类的Perl模块是Unicode::Collate
。
更新:您还可以将use locale
与use locale;
use POSIX qw(setlocale LC_ALL);
setlocale(LC_ALL, ''); # Set default locale from environment variables
一起使用:
sort
这使得cmp
和printf
等内置函数使用区域设置规则来排序字符串。不过要小心;更改程序的语言环境可能会产生意外后果,例如在Unicode::Collate
输出中将小数点更改为逗号。
更新2: POSIX语言环境显然以各种方式被破坏。您最好使用Unicode::Collate::Locale
和{{1}}。
答案 2 :(得分: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