考虑以下Ruby代码分析三字节UTF-8字符串:
#encoding: utf-8
s = "\x65\xCC\x81"
p [s.bytesize, s.length, s, s.encoding.name]
#=> [3, 2, "é", "UTF-8"]
如上所述[{3}},上面的 是一个双字符的字符串:拉丁文小写e
后跟on this page of mine。但是,它看起来像一个字符,这在布局固定宽度显示时很重要。
例如,查看Combining Acute Accent上“moiré.svg”的两个条目,并注意其中一个条目如何搞乱列对齐。
如何计算Ruby中字符串的“等宽视觉长度”,它不包含任何零宽度组合字符? (一种有效的技术可能是将Unicode字符串转换为其规范表示的方法,将上述内容转换为"\xC3\xA9"
,其中é
看起来像length
但1
{{1}} 。)
答案 0 :(得分:5)
unicode_utils gem可能有所帮助:
http://unicode-utils.rubyforge.org/UnicodeUtils.html
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
。
(感谢Michael Anderson指出了其他方法)
答案 1 :(得分: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's answer中建议的unicode_utils gem可能是更好的选择,但我想我会将其包含在内以保证完整性。
答案 2 :(得分:-1)
我远不是Ruby的专家,但是this给出了以下内容:
def length_utf8
count = 0
scan(/./mu) { count += 1 }
count
end