solo regulares regular online numeros net ismatch expresiones example ejemplos regex r strsplit

regex - regulares - ¿Por qué strsplit usa lookahead positivo y mira detrás de la afirmación coincide de manera diferente?



regex.ismatch c# (3)

No estoy seguro de si esto califica como un error, porque creo que este es un comportamiento esperado basado en la documentación de R. De ?strsplit :

El algoritmo aplicado a cada cadena de entrada es

repeat { if the string is empty break. if there is a match add the string to the left of the match to the output. remove the match and all to the left of it. else add the string to the output. break. }

Tenga en cuenta que esto significa que si hay una coincidencia al principio de una cadena (no vacía), el primer elemento de la salida es "" "'', pero si hay una coincidencia al final de la cadena, la salida es Lo mismo que con el partido eliminado.

El problema es que las aserciones de lookahead (y look behind) son de longitud cero. Así, por ejemplo, en este caso:

FF <- "(?=funky)" testString <- "take me to funky town" gregexpr(FF,testString,perl=TRUE) # [[1]] # [1] 12 # attr(,"match.length") # [1] 0 # attr(,"useBytes") # [1] TRUE strsplit(testString,FF,perl=TRUE) # [[1]] # [1] "take me to " "f" "unky town"

Lo que sucede es que el lookahead solitario (?=funky) coincide en la posición 12. Así que la primera división incluye la cadena hasta la posición 11 (a la izquierda de la coincidencia), y se elimina de la cadena, junto con la coincidencia, que - sin embargo- tiene longitud cero.

Ahora la cadena restante es funky town , y la búsqueda anticipada coincide en la posición 1. Sin embargo, no hay nada que eliminar, porque no hay nada a la izquierda de la coincidencia, y la coincidencia en sí tiene una longitud cero. Así que el algoritmo está atascado en un bucle infinito. Aparentemente, R resuelve esto dividiendo un solo carácter, que incidentalmente es el comportamiento documentado cuando se strsplit con una expresión regular vacía (cuando el argumento se split="" ). Después de esto, la cadena restante es unky town , que se devuelve como la última división ya que no hay coincidencia.

Las miradas no son un problema, porque cada coincidencia se divide y se elimina de la cadena restante, por lo que el algoritmo nunca se atasca.

Es cierto que este comportamiento parece extraño a primera vista. Sin embargo, comportarse de otro modo violaría la suposición de longitud cero para lookaheads. Dado que el algoritmo strsplit está documentado, creo que esto no cumple con la definición de un error.

El sentido común y una comprobación de cordura con gregexpr() indican que las aseveraciones de mirar hacia atrás y hacia adelante a continuación deben coincidir en exactamente una ubicación en testString :

testString <- "text XX text" BB <- "(?<= XX )" FF <- "(?= XX )" as.vector(gregexpr(BB, testString, perl=TRUE)[[1]]) # [1] 9 as.vector(gregexpr(FF, testString, perl=TRUE)[[1]][1]) # [1] 5

strsplit() , sin embargo, usa esas ubicaciones de emparejamiento de manera diferente, dividiendo testString en una ubicación cuando usa la afirmación de mirar por detrás, pero en dos ubicaciones, la segunda de las cuales parece incorrecta, cuando se usa la afirmación de búsqueda hacia delante.

strsplit(testString, BB, perl=TRUE) # [[1]] # [1] "text XX " "text" strsplit(testString, FF, perl=TRUE) # [[1]] # [1] "text" " " "XX text"

Tengo dos preguntas: (P1) ¿Qué está pasando aquí? Y (Q2) ¿cómo se puede lograr que strsplit() se comporte mejor?

Actualización: la excelente respuesta de Theodore Lytras explica lo que está sucediendo y las direcciones (Q1) . Mi respuesta se basa en la suya para identificar un remedio, el direccionamiento (Q2) .


Parece un error para mí. Esto no solo parece estar relacionado con espacios, específicamente, sino con cualquier look solitario (positivo o negativo):

FF <- "(?=funky)" testString <- "take me to funky town" strsplit(testString,FF,perl=TRUE) # [[1]] # [1] "take me to " "f" "unky town" FF <- "(?=funky)" testString <- "funky take me to funky funky town" strsplit(testString,FF,perl=TRUE) # [[1]] # [1] "f" "unky take me to " "f" "unky " # [5] "f" "unky town" FF <- "(?!y)" testString <- "xxxyxxxxxxx" strsplit(testString,FF,perl=TRUE) # [[1]] # [1] "xxx" "y" "xxxxxxx"

Parece funcionar bien si se le da algo para capturar junto con la afirmación de ancho cero, como por ejemplo:

FF <- " (?=XX )" testString <- "text XX text" strsplit(testString,FF,perl=TRUE) # [[1]] # [1] "text" "XX text" FF <- "(?= XX ) " testString <- "text XX text" strsplit(testString,FF,perl=TRUE) # [[1]] # [1] "text" "XX text"

Tal vez algo así podría funcionar como una solución.


Sobre la base de la cuidadosa explicación de Theodore Lytras del comportamiento de substr() , una solución razonablemente limpia es prefijar la aserción de lookahead para ser compatible con una aserción de mirada positiva que coincida con cualquier carácter individual:

testString <- "take me to funky town" FF2 <- "(?<=.)(?=funky)" strsplit(testString, FF2, perl=TRUE) # [[1]] # [1] "take me to " "funky town"