ruby - ¿Interfiere el carácter multibyte con el carácter de la línea final dentro de una expresión regular?
regex encoding (2)
El problema que reportó es definitivamente un error de Regexp
de RUBY_VERSION #=> "2.0.0"
pero ya existe en la versión 1.9 anterior cuando la codificación permite caracteres de varios bytes como __ENCODING__ #=> #<Encoding:UTF-8>
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.
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 codificación de cadena es UTF-8, y el sistema operativo es Linux (es decir, $/
es "/n"
). ¿Los caracteres multibyte interfieren con $/
? ¿Cómo?
En Ruby trunk , el problema ahora ha sido aceptado como un error. Con suerte, será arreglado.
Actualización: Dos parches se han publicado en Ruby trunk.