regulares regular probar negacion expresiones expresion espacio ejemplos cuantificadores blanco basicas alfanumerico regex r stringr

regex - negacion - probar expresiones regulares



Coincidencia de expresiones regulares de cadenas no codiciosas (2)

Concepto difícil, así que haré mi mejor esfuerzo ... Alguien puede editarlo y explicarlo mejor si es un poco confuso.

Las expresiones que coinciden con sus patrones se buscan de izquierda a derecha. Sí, todas las siguientes cadenas aaaab , aaaab , aaab y ab coinciden con su patrón, pero aaaab es la que se inicia más a la izquierda y es la que se devuelve.

Así que aquí, tu patrón no codicioso no es muy útil. Tal vez este otro ejemplo te ayude a comprender mejor cuando se inicia un patrón no codicioso:

str_match(''xxx aaaab yyy'', "a.*?y") # [,1] # [1,] "aaaab y"

Aquí todas las cadenas aaaab y , aaaab yy , aaaab yyy coincidieron con el patrón y comenzaron en la misma posición, pero la primera se devolvió debido al patrón no codicioso.

Entonces, ¿qué puedes hacer para atrapar ese último ab ? Utilizar esta:

str_match(''xxx aaaab yyy'', ".*(a.*b)") # [,1] [,2] # [1,] "xxx aaaab" "ab"

¿Como funciona? Al agregar un patrón codicioso .* En el frente, ahora está obligando al proceso a colocar la última a posible en el grupo capturado.

Estoy bastante seguro de que me estoy perdiendo algo obvio aquí, pero no puedo hacer que R use expresiones regulares no codiciosas:

> library(stringr) > str_match(''xxx aaaab yyy'', "a.*?b") [,1] [1,] "aaaab"

Las funciones básicas se comportan de la misma manera:

> regexpr(''a.*?b'', ''xxx aaaab yyy'') [1] 5 attr(,"match.length") [1] 5 attr(,"useBytes") [1] TRUE

Espero que la coincidencia sea solo ab según el comentario ''codicioso'' en http://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html :

Por defecto, la repetición es codiciosa, por lo que se utiliza el máximo número posible de repeticiones. Esto se puede cambiar a ''mínimo'' añadiendo? al cuantificador. (Hay otros cuantificadores que permiten una comparación aproximada: consulte la documentación de TRE).

¿Podría alguien explicarme qué está pasando?

Actualizar. Lo que es una locura es que, en otros casos, los patrones no codiciosos se comportan como se espera:

> str_match(''xxx <a href="abc">link</a> yyy <h1>Header</h1>'', ''<a.*>'') [,1] [1,] "<a href=/"abc/">link</a> yyy <h1>Header</h1>" > str_match(''xxx <a href="abc">link</a> yyy <h1>Header</h1>'', ''<a.*?>'') [,1] [1,] "<a href=/"abc/">"


El problema es hacer coincidir la ventana más corta entre dos cadenas . @flodel menciona correctamente que un motor de expresiones regulares está analizando la cadena de izquierda a derecha y, por lo tanto, todas las coincidencias son las más a la izquierda . La codicia y la pereza solo se aplican a los límites de la derecha: los cuantificadores codiciosos hacen que las subcadenas lleguen hasta los límites de la derecha, y los perezosos coincidirán con la primera aparición de los subpatrones a seguir.

Vea los ejemplos :

> library(stringr) > str_extract(''xxx aaaab yyy'', "a[^ab]*b") [1] "ab" > str_extract(''xxx aaa xxx aaa zzz'', "xxx.*?zzz") [1] "xxx aaa xxx aaa zzz" > str_extract(''xxx aaa xxx aaa zzz'', "xxx(?:(?!xxx|zzz).)*zzz") [1] "xxx aaa zzz"

El primer y el tercer escenario devuelven la ventana más corta, el segundo es una ilustración del problema actual pero con una entrada de caracteres múltiples.

Escenario 1. Los límites son caracteres únicos.

En el caso de que a y b sean caracteres únicos, la ventana más corta se encuentra utilizando una clase de caracteres negados. a[^ab]*b agarrará fácilmente la subcadena desde a hasta la siguiente b sin a s y b s en medio.

Escenario 2. Los límites no son caracteres individuales

Puede usar un token codicioso templado en estos casos que se pueden desenrollar aún más. El patrón xxx(?:(?!xxx|zzz).)*zzz coincide con xxx , luego cualquier otro carácter 0+ que no sea un char de linebreak que no sea el carácter inicial de una secuencia de caracteres xxx o zzz (the (?!xxx|zzz) es un lookahead negativo que falla la coincidencia si la subcadena inmediatamente a la derecha coincide con el patrón de lookahead), y luego un zzz .

Estos escenarios coincidentes se pueden usar fácilmente con los regmatches base R (usando un sabor de expresión regular PCRE que admita lookaheads):

> x <- ''xxx aaa xxx aaa zzz xxx bbb xxx ccc zzz'' > unlist(regmatches(x, gregexpr("xxx(?:(?!xxx|zzz).)*zzz", x, perl = TRUE))) [1] "xxx aaa zzz" "xxx ccc zzz"

Una nota: cuando se utiliza una expresión regular de PCRE en la base R, o la expresión regular de la ICU en str_extract / str_match , el . no coincide con los caracteres de salto de línea, para habilitar ese comportamiento, debe agregar (?s) al inicio del patrón (un modificador DOTALL en línea).