Con esta expresión regular:
regex1 = /\z/
las siguientes cadenas coinciden:
"hello" =~ regex1 # => 5 "こんにちは" =~ regex1 # => 5
Pero con estas expresiones regulares:
regex2 = /#$/?\z/ regex3 = /\n?\z/
muestran diferencia
"hello" =~ regex2 # => 5 "hello" =~ regex3 # => 5 "こんにちは" =~ regex2 # => nil "こんにちは" =~ regex3 # => nil
¿Qué está interfiriendo? La encoding de cadena es UTF-8, y el sistema operativo es Linux (es decir, $/
es "\n"
). ¿Los caracteres multibyte interfieren con $/
? ¿Cómo?
El problema que reportaste es definitivamente un error de Regexp
de RUBY_VERSION #=> "2.0.0"
pero ya existe en la versión 1.9 anterior cuando la encoding permite caracteres de varios bytes como __ENCODING__ #=> #
No depende de Linux, es posible reproducir el mismo comportamiento en OSX y Windows también.
Mientras tanto, el error 8210 se solucionará, podemos ayudar aislando y entendiendo los casos en que ocurre el problema. Esto también puede ser útil para cualquier solución cuando sea aplicable a casos específicos.
Entiendo que el problema ocurre cuando:
\z
. ?
El error puede deberse a malentendidos entre el número de bytes y el número de caracteres que realmente verifica el motor de expresiones regulares.
Algunos ejemplos pueden ayudar:
s = "んにちは"
s =~ /ん?\z/u #=> 4" # OK it works 3 == 3
s =~ /ç?\z/u #=> nil # KO: BUG when 3 > 2 s =~ /x?ç?\z/u #=> 4 # OK it works 3 == ( 1+2 )
s =~ /\n?\z/u #=> nil" # KO: BUG when 3 > 1 s =~ /\n?\n?\z/u #=> nil" # KO: BUG when 3 > 2 s =~ /\n?\n?\n?\z/u #=> 4" # OK it works 3 == ( 1+1+1)
Por los resultados de TEST1 podemos afirmar: si el último carácter de múltiples bytes de la cadena es de 3 bytes, entonces la prueba de ‘cero o uno antes’ solo funciona cuando probamos al menos 3 bytes (no 3 caracteres) antes.
s = "in French there is the ç"
s =~ /ん?\z/u #=> 24 # OK 2 <= 3
s =~ /é?\z/u #=> 24 # OK 2 == 2 s =~ /x?é?\z/u #=> 24 # OK 2 < (2+1)
s =~ /\n?\z/u #=> nil # KO 2 > 1 ( the BUG occurs ) s =~ /\n?\n?\z/u #=> 24 # OK 2 == (1+1) s =~ /\n?\n?\n?\z/u #=> 24 # OK 2 < (1+1+1)
Por los resultados de TEST2 podemos afirmar: si el último carácter de múltiples bytes de la cadena es de 2 bytes, entonces la prueba de 'cero o uno antes' solo funciona cuando verificamos al menos 2 bytes (no 2 caracteres) antes.
Cuando el carácter de varios bytes no está al final de la cadena, encontré que funciona correctamente.
gist público con mi código de prueba disponible aquí
En Ruby trunk , el problema ahora ha sido aceptado como un error. Con suerte, será arreglado.
Actualización: Dos parches han sido publicados en Ruby trunk.