2011-08-10 22 views
7

Tôi có một số văn bản chứa chuỗi thoát Unicode như \ u003C. Đây là những gì tôi đã đưa ra để không dò tìm nó:Đây có phải là cách tốt nhất để unescape unicode thoát chuỗi trong Ruby?

string.gsub(/\u(....)/) {|m| [$1].pack("H*").unpack("n*").pack("U*")}

Is it correct? (có vẻ như nó hoạt động với các thử nghiệm của tôi, nhưng ai đó có thể hiểu biết hơn về vấn đề này?)

+0

Đúng vậy. Nó đến từ Rails 'ActiveSupport :: JSON và nhận được giải mã bởi ActiveSupport :: JSON, nhưng nó không giải mã được \ u thoát đúng cách. (trên Rails 2.1.2) –

Trả lời

17

Regex của bạn, /\u(....)/, có một số vấn đề.

Trước hết, \u không hoạt động theo cách bạn nghĩ, trong 1.9 bạn sẽ gặp lỗi và trong 1.8 nó sẽ chỉ khớp với một u đơn lẻ thay vì cặp \u mà bạn đang tìm kiếm; bạn nên sử dụng /\\u/ để tìm số \u theo nghĩa đen mà bạn muốn.

Thứ hai, nhóm (....) của bạn quá dễ dãi, điều đó sẽ cho phép bất kỳ bốn ký tự nào thông qua và đó không phải là những gì bạn muốn. Trong 1.9, bạn muốn (\h{4}) (bốn chữ số thập lục phân) nhưng trong 1.8 bạn cần ([\da-fA-F]{4})\h là một điều mới.

Vì vậy, nếu bạn muốn regex hoạt động ở cả 1.8 và 1.9, bạn nên sử dụng /\\u([\da-fA-F]{4})/. Điều này cho phép bạn sau đây trong 1.8 và 1.9:

>> s = 'Where is \u03bc pancakes \u03BD house? And u1123!' 
=> "Where is \\u03bc pancakes \\u03BD house? And u1123!" 
>> s.gsub(/\\u([\da-fA-F]{4})/) {|m| [$1].pack("H*").unpack("n*").pack("U*")} 
=> "Where is μ pancakes ν house? And u1123!" 

Sử dụng packunpack để mangle số hex vào một ký tự Unicode có lẽ là đủ tốt nhưng có thể có những cách tốt hơn.

+1

Cũng có thể hữu ích để thêm điều này như là một phần mở rộng cho lớp String (tôi đã sử dụng String # utf8_decode). – Mikey

Các vấn đề liên quan