如何在 Perl 中枚举所有 Unicode 规范等效序列?

Posted

技术标签:

【中文标题】如何在 Perl 中枚举所有 Unicode 规范等效序列?【英文标题】:How to enumerate all Unicode canonically equivalent sequences in Perl? 【发布时间】:2011-09-19 03:12:25 【问题描述】:

是否存在一个标准的 Perl 模块或函数,给定一个 Unicode Combining Character Sequence(或更一般地说,一个任意的 Unicode 文本字符串),将生成所有规范等效字符串的列表?

例如,如果给定字符 U+1EAD,我想返回所有这些规范等效序列的列表:

0061 0302 0323
0061 0323 0302
00E2 0323
1EA1 0302
1EAD

(我并不特别关心接口是根据 USV 数组还是 utf 字符串。)

【问题讨论】:

Unicode::Normalize 则相反。我不知道有什么可以满足您的要求。 fwiw,好奇的人可能想知道我为什么要这样做,并且有几个用途:一个是为其他代码构建测试数据;另一个是在字体内部构建 OpenType 逻辑,以便它们可以正确显示所有规范等效的序列。 我认为可以使用蛮力解决方案(通过在输入的 NFD 形式的排列子串上使用 NFC),但不能这样做。 0915 093C 在规范上等同于 0958,但无法使用 NFC 从 0915 093C0958 我认为输入需要是一个Extended Grapheme Cluster而不是一个Combining Character Sequence来处理HANGUL SYLLABLE GA的分解。跨度> 【参考方案1】:

这是 XY 问题吗?如果您想比较/匹配 2 个 unicode 字符串,并且担心编码重音字符的不同方式会产生误报,那么最好的方法是使用 Unicode 中的规范化函数之一来规范化 2 个字符串::标准化,在进行比较或匹配之前。

否则会有点乱。

可以使用charnames::viacode(0x1EAD); 获得完整的字符名称(对于 U+1EAD,它将是带有圆形和点的拉丁小写字母 A),并获得通过在 WITH|AND 上拆分名称来组成各种字符。然后您可以生成基本字符 + 修饰符和其他修饰符的所有组合(检查它们是否存在!)。此时您将遇到将全名中的组合字符名称(例如CIRCUMFLEX)与组合字符实名(COMBINING CIRCUMFLEX ACCENT)匹配的问题。这可能有规则,但我不知道。

这可能是我的幼稚尝试,可能有更好的方法可以做到这一点,但到目前为止还没有人自愿提供信息......

【讨论】:

据我了解,OP 要求某种方法,当使用“'A' 加 'ring'” 时,将返回所有可能的字符,这些字符归一化为 'A'+'ring' ,包括单例-Angstroem 字符,它本身永远不会是规范化的结果。有趣。 就我的目的而言,是否包括单例分解应该是可选的,但是是的,Kerrek,你有基本的想法。我有一个算法可以满足我的需要——我只是想知道是否已经有标准的方法可以做到这一点——如果没有,我将努力在 CPAN 上发布一个模块。 可以使用前面提到的 Unicode::Normalize 的 NFD 将字形分解成各种组成字符。无需解析字符名,我不会在所有情况下都使用它(例如 HANGUL SYLLABLE GA)。

以上是关于如何在 Perl 中枚举所有 Unicode 规范等效序列?的主要内容,如果未能解决你的问题,请参考以下文章