reuse regular patterns online one negative look expressions example around regex lookahead negative-lookahead

regex - patterns - Expresión regular lookahead negativo



regex online (3)

En mi directorio de inicio tengo una carpeta drupal-6.14 que contiene la plataforma Drupal.

Desde este directorio utilizo el siguiente comando:

find drupal-6.14 -type f -iname ''*'' | grep -P ''drupal-6.14/(?!sites(?!/all|/default)).*'' | xargs tar -czf drupal-6.14.tar.gz

Lo que hace este comando es gzips la carpeta drupal-6.14 , excluyendo todas las subcarpetas de drupal-6.14 / sites / except sites / all y sites / default , que incluye.

Mi pregunta es sobre la expresión regular:

grep -P ''drupal-6.14/(?!sites(?!/all|/default)).*''

La expresión funciona para excluir todas las carpetas que quiero excluir, pero no entiendo muy bien por qué.

Es una tarea común usar expresiones regulares para

Haga coincidir todas las cadenas, excepto aquellas que no contengan el subpatrón x. O en otras palabras, negando un subpatrón.

Yo (creo) entiendo que la estrategia general para resolver estos problemas es el uso de lookaheads negativos, pero nunca he entendido a un nivel satisfactorio cómo funcionan los aspectos positivos y negativos (adelante / atrás).

A lo largo de los años, he leído muchos sitios web sobre ellos. Los manuales de expresiones regulares de PHP y Python, otras páginas como http://www.regular-expressions.info/lookaround.html y demás, pero nunca he tenido una comprensión sólida de ellos.

¿Podría alguien explicar cómo funciona esto y tal vez proporcionar algunos ejemplos similares que harían cosas similares?

- Actualización uno:

Con respecto a la respuesta de Andomar: ¿puede un doble negativo mirar hacia delante expresarse más sucintamente como una única declaración positiva de anticipación:

es decir, es:

''drupal-6.14/(?!sites(?!/all|/default)).*''

equivalente a:

''drupal-6.14/(?=sites(?:/all|/default)).*''

???

- Actualización dos:

De acuerdo con @andomar y @alan Moore, no se puede intercambiar el doble negativo de búsqueda anticipada positiva.


Las miradas se pueden anidar.

Por lo tanto, esta expresión regular coincide con "drupal-6.14 /" que no va seguida de "sitios" que no va seguida de "/ todos" o "/ predeterminado".

¿Confuso? Usando palabras diferentes, podemos decir que coincide con "drupal-6.14 /" que no es seguido por "sitios" a menos que sea seguido por "/ todos" o "/ predeterminado"


Si revisas tu expresión regular de esta manera:

drupal-6.14/(?=sites(?!/all|/default)).* ^^

... entonces coincidirá con todas las entradas que contengan drupal-6.14/ seguido por sites seguidos por cualquier cosa que no sea /all o /default . Por ejemplo:

drupal-6.14/sites/foo drupal-6.14/sites/bar drupal-6.14/sitesfoo42 drupal-6.14/sitesall

Cambiando ?= ?! para que coincida con su expresión regular original simplemente niega esos partidos:

drupal-6.14/(?!sites(?!/all|/default)).* ^^

Entonces, esto simplemente significa que drupal-6.14/ now no puede ser seguido por sites seguidos por cualquier cosa que no sea /all o /default . Entonces, estas entradas satisfarán la expresión regular:

drupal-6.14/sites/all drupal-6.14/sites/default drupal-6.14/sites/all42

Pero, lo que puede no ser obvio por algunas de las otras respuestas (y posiblemente su pregunta) es que su expresión regular también permitirá otras entradas donde drupal-6.14/ es seguido por cualquier cosa que no sea un sites . Por ejemplo:

drupal-6.14/foo drupal-6.14/xsites

Conclusión: Entonces, su expresión regular básicamente dice que incluya todos los subdirectorios de drupal-6.14 excepto aquellos subdirectorios de sites cuyo nombre comienza con cualquier cosa que no sea all o por default .


Un lookahead negativo dice que, en esta posición, la siguiente expresión regular no puede coincidir.

Tomemos un ejemplo simplificado:

a(?!b(?!c)) a Match: (?!b) succeeds ac Match: (?!b) succeeds ab No match: (?!b(?!c)) fails abe No match: (?!b(?!c)) fails abc Match: (?!b(?!c)) succeeds

El último ejemplo es una doble negación : permite una b seguida de c . La búsqueda anticipada negativa anidada se convierte en una anticipación positiva: la c debería estar presente.

En cada ejemplo, solo el a coincide. La búsqueda anticipada es solo una condición y no se agrega al texto coincidente.