2009-12-21 36 views
14

是否有一種可接受的方式來處理Ruby 1.9中輸入的編碼未知的正則表達式?比方說,我的輸入恰好是UTF-16編碼:Ruby 1.9:輸入編碼未知的正則表達式

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) 

我目前的做法是使用UTF-8內部和重新編碼(副本),如有必要,輸入:

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"> 

但是,這對我來說感覺有些尷尬,我想問問是否有更好的方法來做到這一點。

回答

9

據我所知,沒有更好的方法來使用。但是,我可以提出一個小小的改動嗎?

而不是改變輸入的編碼,爲什麼不改變正則表達式的編碼?每次遇到新編碼時翻譯一個正則表達式字符串比翻譯數百或數千行輸入以匹配正則表達式的編碼要少得多。

# 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) 

在病理情況下(輸入編碼變化,每行),這將是一樣慢,你重新編碼,因爲要在正則表達式通過循環每一次。但在99.9%的情況下,對於數百或數千行的整個文件,編碼是恆定的,這將導致重新編碼的大幅減少。

+0

謝謝!對我來說,它並沒有發生,反過來編碼正則表達式。這確實快了很多! 對於其他嘗試這樣做的人:當您嘗試測試代碼時,請注意虛擬編碼('#dummy?')。花了我一段時間找出爲什麼它不工作。 – DataWraith 2009-12-22 09:57:20

+0

同意表現 - 我發現它記憶正則表達式的指數更快。快速破解這裏來處理空白剝離:https://gist.github.com/mahemoff/c877eb1e955b1160dcdf6f4d4c0ba043 – mahemoff 2016-06-28 09:04:07