如何在ruby 2中修复损坏的UTF-8字符串

时间:2018-03-17 11:43:08

标签: ruby-on-rails ruby ruby-2.3

我有一个输入字符串,认为是UTF-8,但不是,需要修复它。代码在ruby 2中,因此iconv不再存在,并且encode或force_encode没有按预期工作:

[5] pry(main)> a='zg\u0142oszeniem'
=> "zg\\u0142oszeniem"
[6] pry(main)> a.encode("UTF-8", :invalid => :replace, :undef => :replace, :replace => "?")
=> "zg\\u0142oszeniem"
[8] pry(main)> a.encode!(Encoding::UTF_8, :invalid => :replace, :undef => :replace, :replace => "?")
=> "zg\\u0142oszeniem"
[10] pry(main)> a.force_encoding(Encoding::UTF_8)
=> "zg\\u0142oszeniem"

我该如何解决?

1 个答案:

答案 0 :(得分:1)

这是使用正则表达式的解决方案:

a.gsub(/\\u([0-9a-fA-F]{1,5}|10[0-9a-fA-F]{4})/) { $1.hex.chr(Encoding::UTF_8) } 1

它应该适用于该特定字符串:

[1] pry(main)> before = 'zg\u0142oszeniem'
=> "zg\\u0142oszeniem"
[2] pry(main)> before.split('')
=> ["z", "g", "\\", "u", "0", "1", "4", "2", "o", "s", "z", "e", "n", "i", "e", "m"]
[3] pry(main)> after = before.gsub(/\\u([0-9a-fA-F]{1,5}|10[0-9a-fA-F]{4})/) { $1.hex.chr(Encoding::UTF_8) }
=> "zgłoszeniem"
[4] pry(main)> after.split('')
=> ["z", "g", "ł", "o", "s", "z", "e", "n", "i", "e", "m"]

[1] Unicode代码点的范围可以是0到10FFFF 16 definition D9 in Section 3.4, Characters and Encoding),这应该解释为什么上面的正则表达式看起来像这样。