使用Perl在Windows上使用区域设置进行多语言文本排序
我正在构建一个软件,用于对不同语言的书籍索引进行排序。它使用Perl,并使用区域设置以外的键。我正在Unix上开发它,但它需要可移植到Windows。这在原则上是可行的,还是依赖于现场环境,我是不是找错了方向?一句话,Windows确实是我需要它的地方,但我在UNIX环境中开发更舒服。让您可以访问系统的这一部分。它为您提供了使用Perl在Windows上使用区域设置进行多语言文本排序,perl,unicode,locale,multilingual,collation,Perl,Unicode,Locale,Multilingual,Collation,我正在构建一个软件,用于对不同语言的书籍索引进行排序。它使用Perl,并使用区域设置以外的键。我正在Unix上开发它,但它需要可移植到Windows。这在原则上是可行的,还是依赖于现场环境,我是不是找错了方向?一句话,Windows确实是我需要它的地方,但我在UNIX环境中开发更舒服。让您可以访问系统的这一部分。它为您提供了CompareString和获取必要的区域设置id所需的工具 如果您想要/需要定位系统文档,则假定您的起点是Unicode,则基础系统调用名为CompareStringEx,
CompareString
和获取必要的区域设置id所需的工具
如果您想要/需要定位系统文档,则假定您的起点是Unicode,则基础系统调用名为
CompareStringEx
,因为您非常小心地解码所有传入数据,无论其本机编码是什么,然后就可以很容易地使用Unicode::Collate
模块作为起点
如果您想要进行区域设置裁剪,那么您可能需要从Unicode::Collate::locale
开始
解码为Unicode
如果您在全UTF8环境中运行,这很容易,但是如果您受到随机所谓“区域设置”(或者更糟糕的是,微软称之为“代码页”的丑陋事物)的影响,那么您可能需要使用CPANEncode::Locale
模块来帮助您。例如:
use Encode;
use Encode::Locale;
# use "locale" as an arg to encode/decode
@ARGV = map { decode(locale => $_) } @ARGV;
# or as a stream for binmode or open
binmode $some_fh, ":encoding(locale)";
binmode STDIN, ":encoding(console_in)" if -t STDIN;
binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
binmode STDERR, ":encoding(console_out)" if -t STDERR;
my $collator = Unicode::Collate->new();
for my $rec (@recs) {
$rec->{NAME_key} =
$collator->getSortKey( $rec->{NAME} );
}
@srecs = sort {
$b->{AGE} <=> $a->{AGE}
||
$a->{NAME_key} cmp $b->{NAME_key}
} @recs;
(如果是我,我只会使用“:utf8”
作为输出。)
标准排序,加上地区和裁剪 关键是,一旦将所有内容解码为内部Perl格式,就可以在其上使用
Unicode::Collate
和Unicode::Collate::Locale
。这些可能非常简单:
use v5.14;
use utf8;
use Unicode::Collate;
my @exes = qw( x⁷ x⁰ x⁸ x³ x⁶ x⁵ x⁴ x² x⁹ x¹ );
@exes = Unicode::Collate->new->sort(@exes);
say "@exes";
# prints: x⁰ x¹ x² x³ x⁴ x⁵ x⁶ x⁷ x⁸ x⁹
或者它们可以是非常花哨的。这里有一个尝试处理书名的方法:它去掉了主要的文章和零填充数字
my $collator = Unicode::Collate->new(
--upper_before_lower => 1,
--preprocess => {
local $_ = shift;
s/^ (?: The | An? ) \h+ //x; # strip articles
s/ ( \d+ ) / sprintf "%020d", $1 /xeg;
return $_;
};
);
现在只需使用该对象的sort
方法进行排序
有时你需要把这类东西翻过来。例如:
use Encode;
use Encode::Locale;
# use "locale" as an arg to encode/decode
@ARGV = map { decode(locale => $_) } @ARGV;
# or as a stream for binmode or open
binmode $some_fh, ":encoding(locale)";
binmode STDIN, ":encoding(console_in)" if -t STDIN;
binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
binmode STDERR, ":encoding(console_out)" if -t STDERR;
my $collator = Unicode::Collate->new();
for my $rec (@recs) {
$rec->{NAME_key} =
$collator->getSortKey( $rec->{NAME} );
}
@srecs = sort {
$b->{AGE} <=> $a->{AGE}
||
$a->{NAME_key} cmp $b->{NAME_key}
} @recs;
但你通常不必担心这些问题。事实上,如果您希望使用CLDR数据对特定于国家/地区的区域设置进行裁剪,您应该只使用Unicode::Collate::locale
,这正好为构造函数添加了另外一个参数:locale=>$country\u code
use Unicode::Collate::Locale;
$coll = Unicode::Collate::Locale->
new(locale => "fr");
@french_text = $coll->sort(@french_text);
看看这有多容易
但你也可以做其他很酷的事情
use Unicode::Collate::Locale;
my $Collator = new Unicode::Collate::Locale::
locale => "de__phonebook",
level => 1,
normalization => undef,
;
my $full = "Ich müß Perl studieren.";
my $sub = "MUESS";
if (my ($pos,$len) = $Collator->index($full, $sub)) {
my $match = substr($full, $pos, $len);
say "Found match of literal ‹$sub› in ‹$full› as ‹$match›";
}
运行时,表示:
在èIch mü223;Perl studieren.›asèmü223;›中找到了文字èMUESS›的匹配项
以下是Unicode::Collate::Locale
模块自v0.96起的可用区域设置,取自其手册页:
locale名称描述
--------------------------------------------------------------
南非荷兰语
阿拉伯语
阿萨姆人
阿塞拜疆(阿塞拜疆)
白俄罗斯人
保加利亚语
孟加拉语
波斯尼亚语
西里尔语波斯尼亚语(定制为塞尔维亚语)
加泰罗尼亚
捷克语
西威尔士
丹麦语
德乌乌电话簿德语(umlaut为“ae”、“oe”、“ue”)
母羊
世界语
西班牙语
es___传统西班牙语(“ch”和“ll”作为一个字位)
爱沙尼亚语
波斯语
芬兰语(v和w基本相等)
芬兰语电话簿(v和w为独立字符)
菲律宾人
法罗群岛
法语
古吉拉特邦
哈豪萨酒店
夏威夷山楂
嗨,印地语
克罗地亚人
匈牙利语
亚美尼亚语
伊博
是冰岛语吗
日语[1]
哈萨克语
吉隆坡卡拉利苏特酒店
卡纳达
高朝文[2]
康卡尼角
林加拉
立陶宛中尉
拉脱维亚人
马其顿语
马来亚拉姆酒店
马拉蒂先生
马耳他山
nb挪威博克马尔酒店
挪威尼诺尔斯克
北索托
奥姆奥罗莫
还是奥利亚
旁遮普省
光抛光
罗马尼亚人
俄罗斯
梵语
萨米北部东南部
僧伽罗语
僧伽罗语词典(U+0DA5=U+0DA2,0DCA,0DA4)
斯洛伐克语
斯洛文尼亚语
阿尔巴尼亚语
高级塞尔维亚人
拉丁语塞尔维亚语(定制为克罗地亚语)
sv瑞典语(v和w基本相等)
sv__改革瑞典语(v和w作为独立字符)
塔米尔
特鲁古
泰语
茨瓦纳
汤加
土耳其
英国乌克兰人
乌尔都语
六越南语
韦瓦尔泽
沃洛夫
约鲁巴
中弘中文
zh__big5汉语(表意文字:big5顺序)
中国汉字GB2312(表意文字:GB-2312顺序)
汉语拼音(表意文字:拼音顺序)[3]
笔画汉语(表意文字:笔画顺序)[3]
朱音(表意文字:朱音序)[3]
根据默认UCA规则,地区包括chr(切诺基)、de(德语)、en(英语)、ga(爱尔兰)、id(印度尼西亚),
它(意大利语)、ka(格鲁吉亚语)、ms(马来语)、nl(荷兰语)、pt(葡萄牙语)、st(南索托语)、sw(斯瓦希里语)、xh(科萨语)、zu
(祖鲁)。
注
[1] ja:表意文字按JIS X 0208顺序排序。全宽和半宽形状与常规形状相同。这个
平假名和凯特的区别