4

3 バイトの UTF-8 文字列を分析する次の Ruby コードを検討してください。

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

私のこのページで説明されているように、上記は実際には2 文字の文字列です。ラテン語の小文字のe後にCombining Acute Accentが続きます。ただし、1 文字のように見えるため、固定幅ディスプレイをレイアウトする際に問題になります。

たとえば、このディレクトリ リストの「moiré.svg」の 2 つのエントリを見て、そのうちの 1 つで列の配置が乱れていることに注意してください。

ゼロ幅の結合文字を含まないRubyの文字列の「モノスペースの視覚的な長さ」を計算するにはどうすればよいですか? (有効なテクニックの 1 つは、Unicode 文字列を正規表現に変換し、上記の文字列を のように"\xC3\xA9"見えるが、の をé持つようにする方法かもしれません。)length1

4

3 に答える 3

5

The unicode_utils gem may help

There is a char_display_width method:

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

There is a string display_width method:

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

Also look at each_grapheme.

(Thanks Michael Anderson for pointing out the additional methods)

于 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 に答える