¿Interfiere el carácter multibyte con el carácter de la línea final dentro de una expresión regular?

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:

  • buscando algo antes del final de la cadena \z .
  • y el último carácter de la cadena es multi-byte .
  • y la búsqueda anterior utiliza cero o un patrón ?
  • pero el número de cero o un carácter buscado en menos que el número de bytes del último carácter.

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:

PRUEBA 1: donde el último carácter: “は” es de 3 bytes:

 s = "んにちは" 

prueba de cero o uno de ん [3 bytes] antes del final de la cadena:

 s =~ /ん?\z/u #=> 4" # OK it works 3 == 3 

cuando intentamos con ç [2 bytes]

 s =~ /ç?\z/u #=> nil # KO: BUG when 3 > 2 s =~ /x?ç?\z/u #=> 4 # OK it works 3 == ( 1+2 ) 

cuando prueba para cero o uno de \ n [1 bytes]

 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.

PRUEBA 2: donde el último carácter “ç” es 2 bytes

 s = "in French there is the ç" 

compruebe si hay cero o uno de ん [3 bytes] ”

 s =~ /ん?\z/u #=> 24 # OK 2 <= 3 

Compruebe si hay cero o uno de é [2 bytes]

 s =~ /é?\z/u #=> 24 # OK 2 == 2 s =~ /x?é?\z/u #=> 24 # OK 2 < (2+1) 

prueba para cero o uno de \ n [1 bytes]

 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.