2009-12-21 7 views
14

Có cách nào được chấp nhận để xử lý các cụm từ thông dụng trong Ruby 1.9 mà mã hóa đầu vào không xác định? Hãy nói rằng đầu vào của tôi xảy ra là UTF-16 mã hóa:Ruby 1.9: Cụm từ thông dụng với mã hóa đầu vào không xác định

x = "foo<p>bar</p>baz" 
y = x.encode('UTF-16LE') 
re = /<p>(.*)<\/p>/ 

x.match(re) 
=> #<MatchData "<p>bar</p>" 1:"bar"> 

y.match(re) 
Encoding::CompatibilityError: incompatible encoding regexp match (US-ASCII regexp with UTF-16LE string) 

cách tiếp cận hiện tại của tôi là sử dụng UTF-8 trong nội bộ và tái mã hóa (một bản sao của) đầu vào nếu cần thiết:

if y.methods.include?(:encode) # Ruby 1.8 compatibility 
    if y.encoding.name != 'UTF-8' 
    y = y.encode('UTF-8') 
    end 
end 

y.match(/<p>(.*)<\/p>/u) 
=> #<MatchData "<p>bar</p>" 1:"bar"> 

Tuy nhiên, điều này có vẻ hơi khó xử với tôi, và tôi muốn hỏi liệu có cách nào tốt hơn để làm điều đó không.

Trả lời

9

Theo như tôi biết, không có phương pháp nào tốt hơn để sử dụng. Tuy nhiên, tôi có thể đề nghị một sự thay đổi nhỏ?

Thay vì thay đổi mã hóa đầu vào, tại sao không thay đổi mã hóa của regex? Dịch một chuỗi regex mỗi khi bạn gặp một mã hóa mới thì sẽ ít hơn nhiều so với việc dịch hàng trăm hoặc hàng nghìn dòng đầu vào để khớp với mã hóa của regex của bạn.

# Utility function to make transcoding the regex simpler. 
def get_regex(pattern, encoding='ASCII', options=0) 
    Regexp.new(pattern.encode(encoding),options) 
end 



    # Inside code looping through lines of input. 
    # The variables 'regex' and 'line_encoding' should be initialized previously, to 
    # persist across loops. 
    if line.methods.include?(:encoding) # Ruby 1.8 compatibility 
    if line.encoding != last_encoding 
     regex = get_regex('<p>(.*)<\/p>',line.encoding,16) # //u = 00010000 option bit set = 16 
     last_encoding = line.encoding 
    end 
    end 
    line.match(regex) 

Trong trường hợp bệnh lý (nơi mã hóa đầu vào thay đổi mọi dòng) điều này sẽ rất chậm, vì bạn đang mã hóa lại regex mỗi lần qua vòng lặp. Nhưng trong 99,9% các tình huống trong đó mã hóa là hằng số cho toàn bộ tập tin của hàng trăm hoặc hàng nghìn dòng, điều này sẽ dẫn đến việc giảm mã hóa lại.

+0

Cảm ơn! Nó đã không xảy ra với tôi để làm điều đó theo cách khác tròn và mã hóa Regexp. Điều đó thực sự nhanh hơn rất nhiều! Đối với bất kỳ ai khác cố gắng thực hiện việc này: Hãy coi chừng mã hóa giả ('#dummy?') Khi bạn thử kiểm tra mã của mình. Đã cho tôi một thời gian để tìm ra lý do tại sao nó không hoạt động. – DataWraith

+0

Đồng ý về hiệu suất - Tôi thấy nó nhanh hơn theo cấp số nhân để ghi nhớ regex. Nhanh chóng hack tại đây để xử lý các khoảng trắng: https://gist.github.com/mahemoff/c877eb1e955b1160dcdf6f4d4c0ba043 – mahemoff