Ruby中.reverse的奇怪行为

时间:2012-06-10 09:25:32

标签: ruby ruby-on-rails-3

当我尝试在包含撇号的Ruby字符串上调用.reverse时,它会将它们更改为\231\200?。因此,对于包含s’tI调用反向的错误顺序的字符串会导致It\231\200?s,而不是It's。任何想法?

我猜这与多字节安全有关?有解决办法吗?

3 个答案:

答案 0 :(得分:4)

这在ruby 1.9中运行正常,它正确处理unicode:

>> "s’tI".reverse
=> "It’s"

在ruby 1.8中断了,因为它对unicode字符串没有相同的支持,并且那些撇号是非1字节的ascii字符,它们是多字节unicode字符(例如,当编码为UTF-8时)

答案 1 :(得分:0)

问题是你的字符串使用二进制字符而不是Unicode字符。您必须先将二进制字符串解码为Unicode字符串。

irb(main):001:0> "a\u9F9Cb".reverse
=> "b\u9F9Ca"
irb(main):002:0> "a\xE9\xBE\x9Cb".reverse
=> "a\x9C\xBE\xE9b"
irb(main):003:0> "a\xE9\xBE\x9Cb".force_encoding('UTF-8').reverse
=> "b\u9F9Ca"

答案 2 :(得分:0)

正如其他人已经解释过你正在处理utf-8,因此一些字符由多个字节表示。还有一些东西,如组合字符,代理对等。红宝石1.8的逐字节反转忽略所有这一切,所以搞砸了。

Ruby 1.9确实理解字符串编码,但是如果你坚持使用ruby 1.8,rails就有自己的系统来处理utf8 - 你可以在一个字符串上调用mb_chars并找回一些看起来像是string,行为类似于字符串,但以精通unicode的方式实现reversedowncase等方法。例如,您可以

reversed_string = string.mb_chars.reverse