4

考虑以下分析三字节 UTF-8 字符串的 Ruby 代码:

#encoding: utf-8
s = "\x65\xCC\x81"
p [s.bytesize, s.length, s, s.encoding.name]
#=> [3, 2, "é", "UTF-8"]

正如我的这个页面上所描述的那样,上面确实一个两个字符的字符串:拉丁小写e,后跟Combining Acute Accent。但是,它看起来像一个字符,这在布置固定宽度的显示器时很重要。

例如,查看此目录列表中“moiré.svg”的两个条目,并注意其中一个条目是如何弄乱列对齐的。

如何计算 Ruby 中不包含任何零宽度组合字符的字符串的“等宽视觉长度”?(一种有效的技术可能是将 Unicode 字符串转换为其规范表示的方法,将上述转换为"\xC3\xA9"看起来也像é但具有lengthof 的方法1。)

4

3 回答 3

5

unicode_utils gem 可能会有所帮助

有一个char_display_width方法:

require "unicode_utils/char_display_width"
UnicodeUtils.char_display_width("別")  # => 2
UnicodeUtils.char_display_width(0x308) # => 0
UnicodeUtils.char_display_width("a")   # => 1

有一个字符串display_width方法:

require "unicode_utils/display_width"
UnicodeUtils.display_width("別れ") => 4
UnicodeUtils.display_width("12") => 2
UnicodeUtils.display_width("a\u{308}") => 1

还看each_grapheme

(感谢迈克尔安德森指出其他方法)

于 2012-04-05T02:05:50.357 回答
1

您可以使用正则表达式来获取 Unicode 属性:

s = "\x65\xCC\x81"
count = s.each_char.inject(0) do |c, char|
  c += 1 unless char=~/\p{Mn}/
  c
end

puts count #=> 1

这在这种情况下有效,但您必须确定要在更强大的解决方案中排除哪些属性。

使用@joelparkerhenderson 的回答中建议的 unicode_utils gem可能是一个更好的选择,但我想我会为了完整起见将其包括在内。

于 2012-04-05T02:29:45.157 回答
-1

我远不是 Ruby 方面的专家,但这给出了以下内容:

def length_utf8
  count = 0
  scan(/./mu) { count += 1 }
  count
end
于 2012-04-05T01:55:24.887 回答