如何将 UTF8 组合字符转换为 ruby 中的单个 UTF8 字符?
Posted
技术标签:
【中文标题】如何将 UTF8 组合字符转换为 ruby 中的单个 UTF8 字符?【英文标题】:How to convert UTF8 combined Characters into single UTF8 characters in ruby? 【发布时间】:2011-10-19 15:59:57 【问题描述】:某些字符,例如 Unicode 字符“LATIN SMALL LETTER C WITH CARON”可以编码为0xC4 0x8D
,但也可以用“LATIN SMALL LETTER C”和“COMBINING CARON”两个代码点来表示,这是0x63 0xcc 0x8c
。
更多信息在这里:http://www.fileformat.info/info/unicode/char/10d/index.htm
我想知道是否有一个库可以将“LATIN SMALL LETTER C”+“COMBINING CARON”转换为“LATIN SMALL LETTER C WITH CARON”。或者是否有包含这些转换的表格?
【问题讨论】:
请不要考虑 8 位代码单元。只考虑逻辑代码点。您可以使用unicode_utils
转换为 NFC 形式,但这并不能满足您的要求,因为您想要的是不可能的。
【参考方案1】:
通常,您使用 Unicode 规范化来执行此操作。
通过 gem unicode_utils (https://github.com/lang/unicode_utils) 使用 UnicodeUtils.nfkc 应该可以得到你所要求的特定行为; unicode 规范化形式 kC 将使用兼容性分解,然后将字符串转换为组合形式(如果可用)(基本上是您的示例所要求的)。 (您还可以通过规范化形式 c,有时是缩写 NFC 来接近您想要的。
How to replace the Unicode gem on Ruby 1.9? 有更多详细信息。
在 Ruby 1.8.7 中,您需要 gem install Unicode,有一个类似的功能可用。
编辑添加:您可能需要规范化形式 kC 而不仅仅是规范化形式 C 的主要原因是连字(由于历史/印刷原因被挤在一起的字符)将首先分解为单个字符,这如果您正在进行字典排序或搜索,有时是可取的)。
【讨论】:
您假设存在这样的预组合字符。这不是一个好的假设。请注意 U+0035 ‹5›DIGIT FIVE
后跟 U+0304 ‹◌̄›COMBINING MACRON
在 NFC 中的渲染时间并不比在 NFD 中更短。只有少数遗留代码点具有预组合字符。大多数没有。
不,我说“如果有的话”。没有做这样的假设。【参考方案2】:
String#encode 从 Ruby 1.9 开始就可以使用了。 UTF-8-MAC 是 NFD 的变体。 U+2000 和 U+2FFF,或 U+F900 和 U+FAFF,或 U+2F800 和 U+2FAFF 之间的代码点不会被分解。有关详细信息,请参阅https://developer.apple.com/library/mac/qa/qa1173/_index.html。 UTF-8-HFS 也可以代替 UTF-8-MAC 使用。
# coding: utf-8
s = "\u010D"
s.encode!('UTF-8-MAC', 'UTF-8')
s.force_encoding('UTF-8')
p "\x63\xcc\x8c" == s
p "\u0063" == s[0]
p "\u030C" == s[1]
【讨论】:
【参考方案3】:这些转化并不总是存在。例如,U+0063 (c) 与 U+030C(组合 caron)的组合可以表示为单个字符,但没有预先组合的字符表示带有 caron (w̌) 的小写“w”。
尽管如此,存在可以在可能的情况下执行此组合的库。寻找一个名为“NFC”(规范化形式:组合)的 Unicode 函数。参见,例如:http://unicode-utils.rubyforge.org/classes/UnicodeUtils.html#M000015
【讨论】:
以上是关于如何将 UTF8 组合字符转换为 ruby 中的单个 UTF8 字符?的主要内容,如果未能解决你的问题,请参考以下文章