如何在 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 093C
到 0958
。
我认为输入需要是一个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 规范等效序列?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 perl 正则表达式替换命令中使用 unicode 字符?
如何在 perl 正则表达式中组合多个 Unicode 属性?