Regular Expressions La codicia contra la pereza


Ejemplo

Dada la siguiente entrada:

aaaaaAlazyZgreeedyAlaaazyZaaaaa

Usaremos dos patrones: uno codicioso: A.*Z , y uno perezoso: A.*?Z Estos patrones producen las siguientes coincidencias:

  • A.*Z produce 1 coincidencia: AlazyZgreeedyAlaaazyZ (ejemplos: Regex101 , Rubular )
  • A.*?Z produce 2 coincidencias: AlazyZ y AlaaazyZ (ejemplos: Regex101 , Rubular )

Primero enfócate en lo que A.*Z hace. Cuando coincidió con la primera A , el .* , Siendo codicioso, luego trata de hacer coincidir tantos . como sea posible.

aaaaaAlazyZgreeedyAlaaazyZaaaaa
     \________________________/
      A.* matched, Z can't match

Dado que la Z no coincide, el motor retrocede, y .* Debe coincidir con uno menos . :

aaaaaAlazyZgreeedyAlaaazyZaaaaa
     \_______________________/
      A.* matched, Z can't match

Esto sucede unas cuantas veces más, hasta que finalmente se llega a esto:

aaaaaAlazyZgreeedyAlaaazyZaaaaa
     \__________________/
      A.* matched, Z can now match

Ahora Z puede coincidir, por lo que el patrón general coincide:

aaaaaAlazyZgreeedyAlaaazyZaaaaa
     \___________________/
      A.*Z matched

Por el contrario, la repetición reacia (perezosa) en A.*?Z primero coincide con pocas . como sea posible, y luego tomar más . según sea necesario. Esto explica por qué encuentra dos coincidencias en la entrada.

Aquí hay una representación visual de lo que los dos patrones combinaron:

aaaaaAlazyZgreeedyAlaaazyZaaaaa
     \____/l      \______/l      l = lazy
     \_________g_________/       g = greedy

Ejemplo basado en respuesta hecha por poligenelubricantes .

El estándar POSIX no incluye el ? Operador, muchos motores de expresiones regulares POSIX no tienen una comparación perezosa. Mientras que la refactorización, especialmente con el "mejor truco" , puede ayudar a emparejar, en algunos casos, la única manera de tener un verdadero juego perezoso es usar un motor que lo soporte.