如何在 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 规范等效序列?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中规范化 Unicode 数字

如何在 perl 正则表达式替换命令中使用 unicode 字符?

如何在 Perl 中找到 Unicode 字符串的长度?

如何在 perl 正则表达式中组合多个 Unicode 属性?

如何在 Perl 中仅匹配 Unicode 字符串中的完全组合字符?

如何在 Perl POD 派生的手册页中使用 Unicode 字符?