内容

名称

Unicode::Collate - Unicode 排序算法

概要

use Unicode::Collate;

#construct
$Collator = Unicode::Collate->new(%tailoring);

#sort
@sorted = $Collator->sort(@not_sorted);

#compare
$result = $Collator->cmp($a, $b); # returns 1, 0, or -1.

注意:@not_sorted$a$b 中的字符串根据 Perl 的 Unicode 支持进行解释。参见 perlunicodeperluniintroperlunitutperlunifaqutf8。否则,您可以使用 preprocess 或在使用前对其进行解码。

描述

此模块是 Unicode 技术标准 #10(又名 UTS #10) - Unicode 排序算法(又名 UCA)的实现。

构造函数和定制

new 方法返回一个排序器对象。如果在没有参数的情况下调用 new(),则排序器应该执行默认排序。

$Collator = Unicode::Collate->new(
   UCA_Version => $UCA_Version,
   alternate => $alternate, # alias for 'variable'
   backwards => $levelNumber, # or \@levelNumbers
   entry => $element,
   hangul_terminator => $term_primary_weight,
   highestFFFF => $bool,
   identical => $bool,
   ignoreName => qr/$ignoreName/,
   ignoreChar => qr/$ignoreChar/,
   ignore_level2 => $bool,
   katakana_before_hiragana => $bool,
   level => $collationLevel,
   long_contraction => $bool,
   minimalFFFE => $bool,
   normalization  => $normalization_form,
   overrideCJK => \&overrideCJK,
   overrideHangul => \&overrideHangul,
   preprocess => \&preprocess,
   rearrange => \@charList,
   rewrite => \&rewrite,
   suppress => \@charList,
   table => $filename,
   undefName => qr/$undefName/,
   undefChar => qr/$undefChar/,
   upper_before_lower => $bool,
   variable => $variable,
);
UCA_Version

如果给出了 UCA 的修订版(以前称为“跟踪版本”)号,则在排序时会模拟该修订版的行为。如果省略,则使用 UCA_Version() 的返回值。

支持以下修订版。默认值为 43。

  UCA       Unicode Standard         DUCET (@version)
-------------------------------------------------------
   8              3.1                3.0.1 (3.0.1d9)
   9     3.1 with Corrigendum 3      3.1.1
  11             4.0.0
  14             4.1.0
  16             5.0.0
  18             5.1.0
  20             5.2.0
  22             6.0.0
  24             6.1.0
  26             6.2.0
  28             6.3.0
  30             7.0.0
  32             8.0.0
  34             9.0.0
  36            10.0.0
  38            11.0.0
  40            12.0.0
  41            12.1.0
  43            13.0.0

* 请参见下方 long_contractionUCA_Version 22 和 24 中的示例。

* 非字符(例如 U+FFFF)不会被忽略,并且可以从 UCA_Version 22 开始被覆盖。

* 超出范围的代码点(大于 U+10FFFF)不会被忽略,并且可以从 UCA_Version 22 开始被覆盖。

* 完全可忽略字符会被忽略,并且在 UCA_Version 9 和 11 中不会中断缩写。

* 在 UCA_Version 9 中,变量之后的可忽略字符处理方式以及某些行为发生了改变。

* 被视为 CJK 统一表意文字的字符(参见 overrideCJK)取决于 UCA_Version

* 许多韩文字母在 UCA_Version 20 中被分配,这将影响 hangul_terminator

alternate

-- 请参见 UTS #10 第 8 版 3.2.2 节“备选权重”。

为了向后兼容,alternate(旧名称)可以用作 variable 的别名。

backwards

-- 请参见 UTS #10 第 3.4 节“反向重音”。

backwards => $levelNumber or \@levelNumbers

权重按逆序排列;例如,法语中的级别 2(重音排序)。如果省略(或 $levelNumberundef\@levelNumbers[]),则在所有级别上都向前排序。

entry

-- 请参见 UTS #10 第 5 节“定制”和第 9.1 节“Allkeys 文件格式”。

如果同一个字符(或字符序列)通过 table 存在于排序元素表中,则映射到排序元素会被覆盖。如果不存在,则会额外定义映射。

entry => <<'ENTRY', # for DUCET v4.0.0 (allkeys-4.0.0.txt)
0063 0068 ; [.0E6A.0020.0002.0063] # ch
0043 0068 ; [.0E6A.0020.0007.0043] # Ch
0043 0048 ; [.0E6A.0020.0008.0043] # CH
006C 006C ; [.0F4C.0020.0002.006C] # ll
004C 006C ; [.0F4C.0020.0007.004C] # Ll
004C 004C ; [.0F4C.0020.0008.004C] # LL
00F1      ; [.0F7B.0020.0002.00F1] # n-tilde
006E 0303 ; [.0F7B.0020.0002.00F1] # n-tilde
00D1      ; [.0F7B.0020.0008.00D1] # N-tilde
004E 0303 ; [.0F7B.0020.0008.00D1] # N-tilde
ENTRY

entry => <<'ENTRY', # for DUCET v4.0.0 (allkeys-4.0.0.txt)
00E6 ; [.0E33.0020.0002.00E6][.0E8B.0020.0002.00E6] # ae ligature as <a><e>
00C6 ; [.0E33.0020.0008.00C6][.0E8B.0020.0008.00C6] # AE ligature as <A><E>
ENTRY

注意:UCA 文件格式中的代码点(在 ';' 之前)必须是 Unicode 代码点(定义为十六进制),而不是本地代码点。因此 0063 必须始终表示 U+0063,而不是 "\x63" 的字符。

权重可能会因排序元素表而异。因此,请确保在 entry 中定义的权重与通过 table 加载的排序元素表中的权重一致。

在 DUCET v4.0.0 中,C 的主权重为 0E60D 的主权重为 0E6D。因此,将 CH 的主权重设置为 0E6A(介于 0E600E6D 之间)会使排序结果为 C < CH < D。准确地说,DUCET 已经在 CD 之间包含了一些字符:小写大写字母 CU+1D04),主权重为 0E64c-hook/C-hookU+0188/U+0187),主权重为 0E65c-curlU+0255),主权重为 0E69。然后,CH 的主权重 0E6A 使 CH 排列在 c-curlD 之间。

hangul_terminator

-- 请参见 UTS #10 第 7.1.4 节“尾随权重”。

如果给定一个真值(非零但应为正数),它将作为终止符主权重添加到每个标准韩文字节的末尾。终止符的次要权重和任何更高权重都设置为零。如果该值为假或hangul_terminator键不存在,则不会执行终止符权重的插入。

韩文字节的边界根据Unicode 标准HangulSyllableType.txt中连字 Jamo 的行为确定。

实现说明:(1)对于扩展映射(Unicode 字符映射到一系列排序元素),即使存在韩文字节边界,也不会在排序元素之间添加终止符。添加终止符仅限于最后一个排序元素的下一个位置。

(2)非连字韩文字符(兼容 Jamo、半角 Jamo 和封闭字符)不会自动以终止符主权重结束。这些字符可能需要事先在排序元素表中包含终止符。

highestFFFF

-- 请参阅 2.4 定制非字符权重,UTS #35 (LDML) 第 5 部分:排序。

如果参数设置为真,则U+FFFF具有最高主权重。当$coll->ge($str, "abc")$coll->le($str, "abc\x{FFFF}")的布尔值为真时,预期$str"abc"或另一个主等效项开头。$str可以是"abcd""abc012",但不应包含U+FFFF,例如"abc\x{FFFF}xyz"

$coll->le($str, "abc\x{FFFF}")几乎类似于$coll->lt($str, "abd"),但后者存在一个问题,即您应该知道哪个字母紧挨着c。对于某些语言,其中ch是下一个字母,"abch"大于"abc\x{FFFF}",但小于"abd"

注意:这等效于(entry => 'FFFF ; [.FFFE.0020.0005.FFFF]')。除了U+FFFF之外的任何其他字符都可以通过entry进行定制。

identical

-- 请参阅 A.3 确定性比较,UTS #10。

默认情况下,权重相等的字符串应该相等,即使它们的代码点不相等。完全可忽略字符将被忽略。

如果参数设置为真,则将使用最终的决胜局级别。如果在通过level指定的级别进行比较后,没有发现权重的差异,则将执行代码点的比较。对于决胜局比较,排序键将附加原始字符串的代码点。完全可忽略字符不会被忽略。

如果应用了preprocess和/或normalization,则使用它们之后(默认情况下为 NFD)的字符串的代码点。

ignoreChar
ignoreName

-- 请参阅 3.6 变量权重,UTS #10。

使表格中的条目完全不可见;即,如同所有级别的权重都为零。

通过 ignoreChar,任何与 qr/$ignoreChar/ 匹配的字符将被忽略。通过 ignoreName,任何其名称(在 table 文件中作为注释给出)与 qr/$ignoreName/ 匹配的字符将被忽略。

例如,当 'a' 和 'e' 可忽略时,'element' 等于 'lament'(或 'lmnt')。

ignore_level2

-- 请参阅 5.1 参数化定制,UTS #10。

默认情况下,区分大小写的比较(即 3 级差异)不会忽略重音符号(即 2 级差异)。

如果参数设置为 true,则即使考虑到大小写,也会忽略重音符号(和其他主要可忽略字符)。

注意level 应为 3 或更大。

katakana_before_hiragana

-- 请参阅 7.2 三级权重表,UTS #10。

默认情况下,平假名在片假名前。如果参数设置为 true,则顺序反转。

注意:此参数简单地假设任何平假名/片假名区分必须发生在 3 级,并且它们在 3 级的权重必须与 UTS #10 中 7.3.1 中提到的权重相同。如果您定义了违反此要求的排序元素,则此参数将无法正常工作。

level

-- 请参阅 4.3 形式排序键,UTS #10。

设置最大级别。任何高于指定级别的级别都将被忽略。

Level 1: alphabetic ordering
Level 2: diacritic ordering
Level 3: case ordering
Level 4: tie-breaking (e.g. in the case when variable is 'shifted')

ex.level => 2,

如果省略,则最大值为 4。

注意:DUCET 在第 4 级包含超过 0xFFFF 的权重。但此模块仅使用 0xFFFF 内的权重。当 variable 为 'blanked' 或 'non-ignorable'(除 'shifted' 和 'shift-trimmed' 外)时,第 4 级可能不可靠。

另请参阅 identical

long_contraction

-- 请参阅 3.8.2 DUCET 的良好格式,4.2 生成数组,UTS #10。

如果参数设置为 true,则对于具有三个或更多字符的缩写(这里称为“长缩写”),将处理初始子字符串。例如,缩写 ABC,其中 A 是起始符,B 和 C 是非起始符(具有非零组合字符类的字符),即使没有 AB 作为缩写,也会被检测到。

默认值:通常为 false。如果 UCA_Version 为 22 或 24,并且 long_contraction 的值未在 new() 中指定,则隐式设置 true 值。这是为了通过 Unicode 6.0.0 和 6.1.0 的一致性测试的解决方法。

change() 函数仅显式处理 long_contraction。如果在 change() 中未指定 long_contraction,即使 UCA_Version 发生改变,long_contraction 也不会改变。

限制:扫描非起始字符是单向的(没有回溯)。如果找到 AB 但没有找到 ABC,则可能无法找到其他以 A 开头且第二个字符不是 B 的长缩写。

(normalization => undef) 下,将跳过不连续缩写的检测步骤。

注意:DUCET 中以下缩写未在步骤 S2.1.1 到 S2.1.3 中考虑,因为它们是不连续的。

0FB2 0F71 0F80 (TIBETAN VOWEL SIGN VOCALIC RR)
0FB3 0F71 0F80 (TIBETAN VOWEL SIGN VOCALIC LL)

例如,TIBETAN VOWEL SIGN VOCALIC RRCOMBINING TILDE OVERLAY (U+0344) 在 NFD 中为 0FB2 0344 0F71 0F80。在这种情况下,检测到 0FB2 0F80 (TIBETAN VOWEL SIGN VOCALIC R),而不是 0FB2 0F71 0F80。插入的 0344 使 0FB2 0F71 0F80 不连续,并且缺少缩写 0FB2 0F71 禁止检测 0FB2 0F71 0F80

minimalFFFE

-- 请参阅 1.1.1 U+FFFE,UTS #35 (LDML) 第 5 部分:排序规则。

如果参数设置为 true,则 U+FFFE 具有最小的主权重。"$a1\x{FFFE}$a2""$b1\x{FFFE}$b2" 之间的比较首先在级别 1 比较 $a1$b1,然后在级别 1 比较 $a2$b2,依此类推。

"ab\x{FFFE}a"
"Ab\x{FFFE}a"
"ab\x{FFFE}c"
"Ab\x{FFFE}c"
"ab\x{FFFE}xyz"
"abc\x{FFFE}def"
"abc\x{FFFE}xYz"
"aBc\x{FFFE}xyz"
"abcX\x{FFFE}def"
"abcx\x{FFFE}xyz"
"b\x{FFFE}aaa"
"bbb\x{FFFE}a"

注意:这等效于 (entry => 'FFFE ; [.0001.0020.0005.FFFE]')。除了 U+FFFE 之外的任何其他字符都可以通过 entry 进行定制。

normalization

-- 请参阅 4.1 规范化,UTS #10。

如果指定,则在准备排序键之前对字符串进行规范化(规范化在预处理之后执行)。

Unicode::Normalize::normalize() 接受的表单名称将作为 $normalization_form 应用。可接受的名称包括 'NFD''NFC''NFKD''NFKC'。有关详细信息,请参阅 Unicode::Normalize::normalize()。如果省略,则使用 'NFD'

normalizationpreprocess(如果已定义)之后执行。

此外,可以使用特殊值 undef"prenormalized",尽管它们与 Unicode::Normalize::normalize() 无关。

如果显式地将undef(而不是字符串"undef")作为此键的值传递,则不会执行任何规范化(如果不需要任何规范化,这可能会使定制更容易)。在(normalization => undef)下,只解析连续的缩写;例如,即使A-ring(和A-ring-cedilla)在Z之后排序,A-cedilla-ring也会与A主等价。在这一点上,(normalization => undef, preprocess => sub { NFD(shift) })等价于(normalization => 'NFD')

(normalization => "prenormalized")的情况下,不会执行任何规范化,但会执行带有组合字符的不连续缩写。因此,(normalization => 'prenormalized', preprocess => sub { NFD(shift) })等价于(normalization => 'NFD')。如果源字符串被精细地预规范化,(normalization => 'prenormalized')可以节省规范化的时间。

除了(normalization => undef)之外,Unicode::Normalize是必需的(另见CAVEAT)。

overrideCJK

--参见7.1派生排序元素,UTS #10。

默认情况下,CJK统一表意文字按Unicode码点顺序排序,但CJK统一表意文字块中的那些小于CJK统一表意文字扩展A中的那些等等。

In the CJK Unified Ideographs block:
U+4E00..U+9FA5 if UCA_Version is 8, 9 or 11.
U+4E00..U+9FBB if UCA_Version is 14 or 16.
U+4E00..U+9FC3 if UCA_Version is 18.
U+4E00..U+9FCB if UCA_Version is 20 or 22.
U+4E00..U+9FCC if UCA_Version is 24 to 30.
U+4E00..U+9FD5 if UCA_Version is 32 or 34.
U+4E00..U+9FEA if UCA_Version is 36.
U+4E00..U+9FEF if UCA_Version is 38, 40 or 41.
U+4E00..U+9FFC if UCA_Version is 43.

In the CJK Unified Ideographs Extension blocks:
Ext.A (U+3400..U+4DB5)   if UCA_Version is  8 to 41.
Ext.A (U+3400..U+4DBF)   if UCA_Version is 43.
Ext.B (U+20000..U+2A6D6) if UCA_Version is  8 to 41.
Ext.B (U+20000..U+2A6DD) if UCA_Version is 43.
Ext.C (U+2A700..U+2B734) if UCA_Version is 20 or later.
Ext.D (U+2B740..U+2B81D) if UCA_Version is 22 or later.
Ext.E (U+2B820..U+2CEA1) if UCA_Version is 32 or later.
Ext.F (U+2CEB0..U+2EBE0) if UCA_Version is 36 or later.
Ext.G (U+30000..U+3134A) if UCA_Version is 43.

通过overrideCJK,可以覆盖CJK统一表意文字(包括扩展)的排序。

例如,CJK统一表意文字按JIS码点顺序排序。

overrideCJK => sub {
    my $u = shift;             # get a Unicode codepoint
    my $b = pack('n', $u);     # to UTF-16BE
    my $s = your_unicode_to_sjis_converter($b); # convert
    my $n = unpack('n', $s);   # convert sjis to short
    [ $n, 0x20, 0x2, $u ];     # return the collation element
},

返回值可以是如上所示的1到4个权重的数组引用。返回值可以是如以下所示的主权重的整数。如果返回undef,将使用默认的派生排序元素。

overrideCJK => sub {
    my $u = shift;             # get a Unicode codepoint
    my $b = pack('n', $u);     # to UTF-16BE
    my $s = your_unicode_to_sjis_converter($b); # convert
    my $n = unpack('n', $s);   # convert sjis to short
    return $n;                 # return the primary weight
},

返回值可以是包含零个或多个数组引用、整数或undef的列表。

例如,忽略所有CJK统一表意文字。

overrideCJK => sub {()}, # CODEREF returning empty list

 # where ->eq("Pe\x{4E00}rl", "Perl") is true
 # as U+4E00 is a CJK unified ideograph and to be ignorable.

如果传递一个假值(包括undef),overrideCJK将不起作用。$Collator->change(overrideCJK => 0)重置旧的。

tableentry中对CJK统一表意文字的权重赋值仍然有效。如果显式地将undef作为此键的值传递,则CJK统一表意文字的权重将被视为未定义。但是,当UCA_Version > 8时,(overrideCJK => undef)没有特殊含义。

注意:除了它们之外,12个CJK兼容表意文字(U+FA0EU+FA0FU+FA11U+FA13U+FA14U+FA1FU+FA21U+FA23U+FA24U+FA27U+FA28U+FA29)也被视为CJK统一表意文字。但是,当您使用DUCET时,它们不能通过overrideCJK覆盖,因为表中包含它们的权重。tableentry优先于overrideCJK

overrideHangul

--参见7.1派生排序元素,UTS #10。

默认情况下,即使 (normalization => undef),韩语音节也会被分解成韩语字母,但韩语音节的映射可以被覆盖。

此参数的工作原理类似于 overrideCJK,因此请参阅该参数的示例。

如果您想覆盖韩语音节的映射,NFD 和 NFKD 不适合,因为 NFD 和 NFKD 会在覆盖之前分解韩语音节。FCD 可能根据情况分解韩语音节。

如果传递一个假值(但不是 undef),overrideHangul 不会生效。$Collator->change(overrideHangul => 0) 会重置旧值。

如果显式地将 undef 作为此键的值传递,则韩语音节的权重将被视为未定义,不会分解成韩语字母。但 tableentry 中对韩语音节的权重定义仍然有效。

overrideOut

-- 请参阅 7.1.1 处理格式错误的代码单元序列,UTS #10。

Perl 似乎允许超出范围的值(大于 0x10FFFF)。默认情况下,当 UCA_Version >= 22 时,超出范围的值将被替换为 U+FFFD(替换字符),或者当 UCA_Version <= 20 时被忽略。

UCA_Version >= 22 时,可以覆盖超出范围的值的权重。虽然 tableentry 可用于它们,但超出范围的值太多。

overrideOut 可以通过算法执行此操作。此参数的工作原理类似于 overrideCJK,因此请参阅该参数的示例。

例如,忽略所有超出范围的值。

overrideOut => sub {()}, # CODEREF returning empty list

如果传递一个假值(包括 undef),overrideOut 不会生效。$Collator->change(overrideOut => 0) 会重置旧值。

关于 U+FFFD 的说明

UCA 建议出于安全原因,不应忽略超出范围的值。例如,"pe\x{110000}rl" 不应该等于 "perl"。但是,在 Unicode 6.0.0 到 6.2.0 的 DUCET 中,U+FFFD 被错误地映射到一个可变排序元素,这意味着当 variable 不是 Non-ignorable 时,超出范围的值将被忽略。

在 Unicode 6.3.0 中,U+FFFD 的映射已得到修正。请参阅 http://www.unicode.org/reports/tr10/tr10-28.html#Trailing_Weights(7.1.4 尾随权重)。此修正已在此处复制。

overrideOut => sub { 0xFFFD }, # CODEREF returning a very large integer

自 Unicode 6.3.0 以来,此解决方法不再需要。

preprocess

-- 请参阅 5.4 预处理,UTS #10。

如果指定,则使用此代码引用在形成排序键之前预处理每个字符串。

例如,删除英文冠词,如 "a" 或 "the"。然后,"the pen" 在 "a pencil" 之前。

preprocess => sub {
      my $str = shift;
      $str =~ s/\b(?:an?|the)\s+//gi;
      return $str;
   },

preprocessnormalization(如果定义)之前执行。

例如,解码使用 legacy 编码(如 shift-jis)的字符串

$sjis_collator = Unicode::Collate->new(
    preprocess => \&your_shiftjis_to_unicode_decoder,
);
@result = $sjis_collator->sort(@shiftjis_strings);

注意:从代码引用返回的字符串将根据 Perl 的 Unicode 支持进行解释。参见 perlunicodeperluniintroperlunitutperlunifaqutf8

rearrange

-- 参见 3.5 重排,UTS #10。

未按逻辑顺序编码且需要重新排列的字符。如果 UCA_Version 等于或小于 11,则默认值为

rearrange => [ 0x0E40..0x0E44, 0x0EC0..0x0EC4 ],

如果要禁止任何重新排列,请将 undef[](对空列表的引用)作为此键的值传递。

如果 UCA_Version 等于或大于 14,则默认值为 [](即不进行重新排列)。

根据 UCA 第 9 版,此参数不应使用;但目前没有发出警告。

rewrite

如果指定,则代码引用用于重写 tableentry 中的行。代码引用将获取每一行,然后应根据 UCA 文件格式返回重写后的行。如果代码引用返回空行,则该行将被跳过。

例如,将所有主要忽略字符重写为三级忽略字符

rewrite => sub {
    my $line = shift;
    $line =~ s/\[\.0000\..{4}\..{4}\./[.0000.0000.0000./g;
    return $line;
},

此示例显示了重写权重。rewrite 允许影响代码点、权重和名称。

注意table 可用于使用另一个表格文件;准备一个修改后的表格一次性完成,比每次读取未修改的表格时重写行效率更高。

suppress

-- 参见 3.12 特殊用途命令,UTS #35 (LDML) 第 5 部分:排序。

以指定字符开头的缩写将被抑制,即使这些缩写是在 table 中定义的。

俄罗斯语和一些使用西里尔字母的语言的示例

suppress => [0x0400..0x0417, 0x041A..0x0437, 0x043A..0x045F],

其中 0x0400 代表 U+0400,西里尔字母大写 IE 带重音。

注意:通过 entry 的缩写不会被抑制。

table

-- 参见 3.8 默认 Unicode 排序元素表,UTS #10。

如果需要,您可以使用另一个排序元素表。

表格文件应位于 @INC 上的 Unicode/Collate 目录中。例如,如果文件名是 Foo.txt,则表格文件将在 @INC 中作为 Unicode/Collate/Foo.txt 进行搜索。

默认情况下,使用 allkeys.txt(作为 DUCET 的文件名)。如果您要准备自己的表格文件,最好使用除 allkeys.txt 之外的任何名称,以避免命名空间冲突。

注意:当使用 XSUB 时,DUCET 会在构建此模块时编译,这可能会在运行时节省时间。显式地说 (table => 'allkeys.txt'),或使用其他表格,或使用 ignoreCharignoreNameundefCharundefNamerewrite 将阻止此模块使用编译后的 DUCET。

如果显式地将 undef 作为此键的值传递,则不会读取任何文件(但您可以通过 entry 定义排序元素)。

定义排序元素表的一种典型方法,无需任何表格文件

$onlyABC = Unicode::Collate->new(
    table => undef,
    entry => << 'ENTRIES',
0061 ; [.0101.0020.0002.0061] # LATIN SMALL LETTER A
0041 ; [.0101.0020.0008.0041] # LATIN CAPITAL LETTER A
0062 ; [.0102.0020.0002.0062] # LATIN SMALL LETTER B
0042 ; [.0102.0020.0008.0042] # LATIN CAPITAL LETTER B
0063 ; [.0103.0020.0002.0063] # LATIN SMALL LETTER C
0043 ; [.0103.0020.0008.0043] # LATIN CAPITAL LETTER C
ENTRIES
 );

如果使用 ignoreNameundefName,则字符名称应在每行上作为注释(在 # 后面)指定。

undefChar
undefName

-- 请参阅 6.3.3 减少字符集,UTS #10。

将排序元素定义为未分配在 table 中。这会减小表格的大小。如果未分配的字符出现在要排序的字符串中,则排序键将由其代码点作为单个字符排序元素组成,因为它大于任何其他已分配的排序元素(在未分配字符的代码点顺序中)。但是,最好忽略您不熟悉且可能从未使用过的字符。

通过 undefChar,任何与 qr/$undefChar/ 匹配的字符都将被定义为未定义。通过 undefName,任何其名称(在 table 文件中作为注释给出)与 qr/$undefName/ 匹配的字符都将被定义为未定义。

例如,超出 BMP 字符的排序权重未存储在对象中

undefChar => qr/[^\0-\x{fffd}]/,
upper_before_lower

-- 请参阅 6.6 大小写比较,UTS #10。

默认情况下,小写字母在字母顺序上排在大写字母之前。如果参数设置为 true,则顺序将反转。

注意:此参数简单地假设任何大小写区分必须发生在级别 3,并且它们在级别 3 的权重必须与 UTS #10 中的 7.3.1 中提到的权重相同。如果您定义的排序元素与此要求不同,则此参数将无法正常工作。

variable

-- 请参阅 3.6 变量权重,UTS #10。

此键允许对可变排序元素进行可变加权,这些元素在表格中用星号标记(注意:在 allkeys.txt 中,许多标点符号和符号是可变的)。

variable => 'blanked', 'non-ignorable', 'shifted', or 'shift-trimmed'.

这些名称不区分大小写。默认情况下(如果省略规范),将采用“shifted”。

'Blanked'        Variable elements are made ignorable at levels 1 through 3;
                 considered at the 4th level.

'Non-Ignorable'  Variable elements are not reset to ignorable.

'Shifted'        Variable elements are made ignorable at levels 1 through 3
                 their level 4 weight is replaced by the old level 1 weight.
                 Level 4 weight for Non-Variable elements is 0xFFFF.

'Shift-Trimmed'  Same as 'shifted', but all FFFF's at the 4th level
                 are trimmed.

排序方法

@sorted = $Collator->sort(@not_sorted)

对字符串列表进行排序。

$result = $Collator->cmp($a, $b)

返回 1(当 $a 大于 $b 时)或 0(当 $a 等于 $b 时)或 -1(当 $a 小于 $b 时)。

$result = $Collator->eq($a, $b)
$result = $Collator->ne($a, $b)
$result = $Collator->lt($a, $b)
$result = $Collator->le($a, $b)
$result = $Collator->gt($a, $b)
$result = $Collator->ge($a, $b)

它们的工作方式与同名运算符相同。

eq : whether $a is equal to $b.
ne : whether $a is not equal to $b.
lt : whether $a is less than $b.
le : whether $a is less than $b or equal to $b.
gt : whether $a is greater than $b.
ge : whether $a is greater than $b or equal to $b.
$sortKey = $Collator->getSortKey($string)

-- 请参阅 4.3 形式排序键,UTS #10。

返回排序键。

您可以使用二进制比较来比较排序键,并使用 UCA 获取字符串比较的结果。

$Collator->getSortKey($a) cmp $Collator->getSortKey($b)

   is equivalent to

$Collator->cmp($a, $b)
$sortKeyForm = $Collator->viewSortKey($string)

将排序键转换为其表示形式。如果 UCA_Version 为 8,则输出略有不同。

use Unicode::Collate;
my $c = Unicode::Collate->new();
print $c->viewSortKey("Perl"),"\n";

# output:
# [0B67 0A65 0B7F 0B03 | 0020 0020 0020 0020 | 0008 0002 0002 0002 | FFFF FFFF FFFF FFFF]
#  Level 1               Level 2               Level 3               Level 4

搜索方法

matchgmatchsubstgsubst 方法分别类似于 m//m//gs///s///g,但它们不识别任何模式,只识别字面子字符串。

免责声明:如果 $Collatorpreprocessnormalization 参数为真,则调用这些方法(indexmatchgmatchsubstgsubst)会抛出异常,因为位置和长度可能与指定字符串上的位置和长度不同。

rearrangehangul_terminator 参数被忽略。katakana_before_hiraganaupper_before_lower 不影响匹配和搜索,因为大小写顺序无关紧要。

$position = $Collator->index($string, $substring[, $position])
($position, $length) = $Collator->index($string, $substring[, $position])

如果 $substring$string 的一部分匹配,则在标量上下文中返回匹配部分首次出现的 位置;在列表上下文中,返回一个包含位置和匹配部分长度的两个元素的列表。

如果 $substring$string 的任何部分都不匹配,则在标量上下文中返回 -1,在列表上下文中返回一个空列表。

例如,当 $str 的内容为 "Ich muß studieren Perl." 时,您可以在 $sub"MüSS" 的情况下执行以下操作:

my $Collator = Unicode::Collate->new( normalization => undef, level => 1 );
                                   # (normalization => undef) is REQUIRED.
my $match;
if (my($pos,$len) = $Collator->index($str, $sub)) {
    $match = substr($str, $pos, $len);
}

并获得 $match 中的 "muß",因为 "muß""MüSS" 相等。

$match_ref = $Collator->match($string, $substring)
($match) = $Collator->match($string, $substring)

如果 $substring$string 的一部分匹配,则在标量上下文中返回 **对** 匹配部分首次出现的 **引用**(如果匹配,$match_ref 始终为真,因为每个引用都是 **真**);在列表上下文中,返回匹配部分的首次出现。

如果 $substring$string 的任何部分都不匹配,则在标量上下文中返回 undef,在列表上下文中返回一个空列表。

例如:

    if ($match_ref = $Collator->match($str, $sub)) { # scalar context
	print "matches [$$match_ref].\n";
    } else {
	print "doesn't match.\n";
    }

     or

    if (($match) = $Collator->match($str, $sub)) { # list context
	print "matches [$match].\n";
    } else {
	print "doesn't match.\n";
    }
@match = $Collator->gmatch($string, $substring)

如果 $substring$string 的一部分匹配,则返回所有匹配的部分(或在标量上下文中返回匹配计数)。

如果 $substring$string 的任何部分都不匹配,则返回一个空列表。

$count = $Collator->subst($string, $substring, $replacement)

如果 $substring$string 的一部分匹配,则匹配部分的首次出现将被 $replacement 替换($string 被修改),并返回 $count(始终等于 1)。

$replacement 可以是 CODEREF,它将匹配的部分作为参数,并返回一个字符串以替换匹配的部分(有点类似于 s/(..)/$coderef->($1)/e)。

$count = $Collator->gsubst($string, $substring, $replacement)

如果$substring$string 的一部分匹配,则所有匹配部分的出现将被替换为$replacement$string 被修改),并返回$count

$replacement 可以是一个CODEREF,以匹配的部分作为参数,并返回一个字符串来替换匹配的部分(有点类似于s/(..)/$coderef->($1)/eg)。

例如:

my $Collator = Unicode::Collate->new( normalization => undef, level => 1 );
                                   # (normalization => undef) is REQUIRED.
my $str = "Camel donkey zebra came\x{301}l CAMEL horse cam\0e\0l...";
$Collator->gsubst($str, "camel", sub { "<b>$_[0]</b>" });

# now $str is "<b>Camel</b> donkey zebra <b>came\x{301}l</b> <b>CAMEL</b> horse <b>cam\0e\0l</b>...";
# i.e., all the camels are made bold-faced.

 Examples: levels and ignore_level2 - what does camel match?
---------------------------------------------------------------------------
 level  ignore_level2  |  camel  Camel  came\x{301}l  c-a-m-e-l  cam\0e\0l
-----------------------|---------------------------------------------------
   1        false      |   yes    yes      yes          yes        yes
   2        false      |   yes    yes      no           yes        yes
   3        false      |   yes    no       no           yes        yes
   4        false      |   yes    no       no           no         yes
-----------------------|---------------------------------------------------
   1        true       |   yes    yes      yes          yes        yes
   2        true       |   yes    yes      yes          yes        yes
   3        true       |   yes    no       yes          yes        yes
   4        true       |   yes    no       yes          no         yes
---------------------------------------------------------------------------
 note: if variable => non-ignorable, camel doesn't match c-a-m-e-l
       at any level.

其他方法

%old_tailoring = $Collator->change(%new_tailoring)
$modified_collator = $Collator->change(%new_tailoring)

更改指定键的值并返回更改的部分。

$Collator = Unicode::Collate->new(level => 4);

$Collator->eq("perl", "PERL"); # false

%old = $Collator->change(level => 2); # returns (level => 4).

$Collator->eq("perl", "PERL"); # true

$Collator->change(%old); # returns (level => 2).

$Collator->eq("perl", "PERL"); # false

并非所有(key,value) 都允许更改。另请参阅@Unicode::Collate::ChangeOK@Unicode::Collate::ChangeNG

在标量上下文中,返回修改后的排序器(但它不是原始排序器的克隆)。

$Collator->change(level => 2)->eq("perl", "PERL"); # true

$Collator->eq("perl", "PERL"); # true; now max level is 2nd.

$Collator->change(level => 4)->eq("perl", "PERL"); # false
$version = $Collator->version()

返回排序器对象使用的table 文件所基于的 Unicode 标准的版本号(字符串)。如果表不包含版本行(以@version 开头),则返回"unknown"

UCA_Version()

返回此模块所参考的 UTS #10 的修订号,该修订号应与所包含的 DUCET 相对应。

Base_Unicode_Version()

返回此模块所参考的 UTS #10 的版本号,该版本号应与所包含的 DUCET 相对应。

EXPORT

不会导出任何方法。

INSTALL

虽然此模块可以在没有任何table 文件的情况下使用,但为了方便使用此模块,建议在 UCA 格式下安装一个table 文件,将其复制到<a place in @INC>/Unicode/Collate 目录下。

最优选的是“默认 Unicode 排序元素表”(又名 DUCET),可从 Unicode 联盟的网站获取

http://www.unicode.org/Public/UCA/

http://www.unicode.org/Public/UCA/latest/allkeys.txt
(latest version)

如果未安装 DUCET,建议将文件从 http://www.unicode.org/Public/UCA/latest/allkeys.txt 手动复制到<a place in @INC>/Unicode/Collate/allkeys.txt

注意事项

规范化

使用 normalization 参数需要 Unicode::Normalize 模块(参见 Unicode::Normalize)。

如果您不需要它(例如,在您不需要处理任何组合字符的情况下),请显式地分配 (normalization => undef)

-- 参见 6.5 避免规范化,UTS #10。

一致性测试

UCA 的一致性测试可在 http://www.unicode.org/Public/UCA/ 下获得。

对于 CollationTest_SHIFTED.txt,应使用通过 Unicode::Collate->new( ) 的排序器;对于 CollationTest_NON_IGNORABLE.txt,应使用通过 Unicode::Collate->new(variable => "non-ignorable", level => 3) 的排序器。

如果 UCA_Version 为 26 或更高版本,则首选 identical 级别;应使用 Unicode::Collate->new(identical => 1)Unicode::Collate->new(identical => 1, variable => "non-ignorable", level => 3)

尝试一致性测试需要 Unicode::Normalize。

EBCDIC 支持处于实验阶段。

作者、版权和许可

Perl 的 Unicode::Collate 模块由 SADAHIRO Tomoyuki 编写,<[email protected]>。此模块版权所有 (C) 2001-2021,SADAHIRO Tomoyuki。日本。保留所有权利。

此模块是自由软件;您可以在与 Perl 本身相同的条款下重新分发它和/或修改它。

文件 Unicode/Collate/allkeys.txt 从 http://www.unicode.org/Public/UCA/13.0.0/allkeys.txt 中逐字复制。对于此文件,版权所有 (c) 2020 Unicode, Inc.;根据 http://www.unicode.org/terms_of_use.html 中的使用条款分发

另请参见

Unicode 排序算法 - UTS #10

http://www.unicode.org/reports/tr10/

默认 Unicode 排序元素表 (DUCET)

http://www.unicode.org/Public/UCA/latest/allkeys.txt

UCA 的一致性测试

http://www.unicode.org/Public/UCA/latest/CollationTest.html

http://www.unicode.org/Public/UCA/latest/CollationTest.zip

韩语音节类型

http://www.unicode.org/Public/UNIDATA/HangulSyllableType.txt

Unicode 规范化形式 - UAX #15

http://www.unicode.org/reports/tr15/

Unicode 地区设置数据标记语言 (LDML) - UTS #35

http://www.unicode.org/reports/tr35/