2009-12-21 9 views
14

¿Hay una forma aceptada de tratar con expresiones regulares en Ruby 1.9 para las cuales se desconoce la codificación de la entrada? Digamos que mi entrada pasa a ser UTF-16 codificado:Ruby 1.9: Expresiones regulares con codificación de entrada desconocida

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) 

Mi enfoque actual es utilizar UTF-8 interna y volver a codificar (una copia de) la entrada si es necesario:

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

Sin embargo, esto se siente un poco incómodo para mí, y quería preguntar si hay una mejor manera de hacerlo.

Respuesta

9

Por lo que yo sé, no hay mejor método para usar. Sin embargo, ¿podría sugerir una ligera alteración?

En lugar de cambiar la codificación de la entrada, ¿por qué no cambiar la codificación de la expresión regular? Traducir una cadena de expresiones regulares cada vez que conoces una nueva codificación es mucho menos trabajo que traducir cientos o miles de líneas de entrada para que coincida con la codificación de tu expresión regular.

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

En el caso patológico (donde la codificación de entrada cambia cada línea) esto sería tan lento, ya que estás volver a codificar la expresión regular cada vez a través del bucle. Pero en el 99.9% de las situaciones en las que la codificación es constante para un archivo completo de cientos o miles de líneas, esto provocará una gran reducción en la recodificación.

+0

¡Gracias! No se me había ocurrido hacerlo al revés y codificar el Regexp. ¡De hecho, es mucho más rápido! Para cualquier otra persona que intente hacer esto: Tenga cuidado con las codificaciones ficticias ('#dummy?') Cuando intente probar su código. Me tomó un tiempo descubrir por qué no estaba funcionando. – DataWraith

+0

De acuerdo sobre el rendimiento: descubrí que es exponencialmente más rápido para memorizar la expresión regular. Quick hack aquí para manejar el espacio en blanco pelado: https://gist.github.com/mahemoff/c877eb1e955b1160dcdf6f4d4c0ba043 – mahemoff

Cuestiones relacionadas