tom*_*ral 6 ruby string ruby-on-rails utf-8 unicode-normalization
在Ruby,Javascript和Java(其他我没试过)中,有西里尔字符Я̆Я̄Я̈长度2.当我尝试用这些字符检查字符串的长度时,我的输出值很差.
"??".mb_chars.length
#=> 2 #should be 1 (ruby on rails)
"??".length
#=> 2 #should be 1 (ruby, javascript)
"?".length
#=> 1 #correct (ruby, javascript)
Run Code Online (Sandbox Code Playgroud)
请注意,字符串以UTF-8编码,每个字符串都表现为单个字符.
我的问题是为什么会有这样的行为,如何在这些字符内正确获取字符串的长度?
根本问题是??实际上是两个代码点:?和变音符号是分开的:
'??'.chars
#=> ["?", "?"]
Run Code Online (Sandbox Code Playgroud)
通常你会通过unicode规范化来解决这类问题,但由于没有单一的代码点??或??(但有),这一点对你没有帮助?.
你可以在检查长度之前剥掉变音符号:
'??'.gsub(/\p{Diacritic}/, '')
#=> "?"
'??'.gsub(/\p{Diacritic}/, '').length
#=> 1
Run Code Online (Sandbox Code Playgroud)
你会得到所需的长度但字符串不会完全相同.这也适用于?可由单个代码点表示的事物:
'?'.length
#=> 1
'?'.gsub(/\p{Diacritic}/, '')
#=> "?"
'?'.gsub(/\p{Diacritic}/, '').length
#=> 1
Run Code Online (Sandbox Code Playgroud)
Unicode非常精彩且令人敬畏,解决了许多困扰我们的问题.不幸的是,Unicode也是可怕和复杂的,因为人类语言和字形并没有完全设计.
Ruby 2.5补充说String#each_grapheme_cluster:
'??????'.each_grapheme_cluster.to_a #=> ["??", "??", "??"]
'??????'.each_grapheme_cluster.count #=> 3
Run Code Online (Sandbox Code Playgroud)
请注意,您不能使用each_grapheme_cluster.size等效的each_char.size,因此6在上面的示例中都会返回.(这看起来像一个错误,我刚刚提交了一份错误报告)
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |