Estoy tratando de dividir una cadena en dos partes usando regex. La cadena tiene el siguiente formato:
text to extract<number>
He estado usando (.*?)<
y <(.*?)>
que funcionan bien, pero después de leer un poco en regex, comencé a preguntarme por qué necesito ?
las expresiones. Solo lo hice así después de encontrarlos a través de este sitio, así que no estoy exactamente seguro de cuál es la diferencia.
Respuestas:
Es la diferencia entre cuantificadores codiciosos y no codiciosos.
Considere la entrada
101000000000100
.Utilizando
1.*1
,*
es codicioso - que coincidirá con todo el camino hasta el final, y luego dar marcha atrás hasta que pueda coincidir1
, dejándole con1010000000001
..*?
No es codicioso.*
no coincidirá con nada, pero luego intentará hacer coincidir caracteres adicionales hasta que coincida1
, finalmente coincidirá101
.Todos los cuantificadores tienen un modo no expansivo:
.*?
,.+?
,.{2,6}?
, e incluso.??
.En su caso, un patrón similar podría ser
<([^>]*)>
: emparejar cualquier cosa menos un signo mayor que (estrictamente hablando, coincide con cero o más caracteres que no sean>
intermedios<
y>
).Ver la hoja de trucos del cuantificador .
fuente
?
difiere del no codicioso??
?"abc"
, la expresión regular/\w\w?\w/
coincidiría con la cadena completa"abc"
, porque?
es codiciosa./\w\w??\w/
es vago, solo coincidirá"ab"
. Solo retrocederá y coincidirá"abc"
si falla más tarde.En codicioso vs no codicioso
La repetición en regex por defecto es codiciosa : intentan igualar tantas repeticiones como sea posible, y cuando esto no funciona y tienen que retroceder, intentan igualar una repetición menos a la vez, hasta que coincida con todo el patrón. encontró. Como resultado, cuando finalmente ocurre una coincidencia, una repetición codiciosa coincidiría con tantas repeticiones como sea posible.
El
?
cuantificador como repetición cambia este comportamiento a no codicioso , también llamado reacio ( en, por ejemplo, Java ) (y a veces "perezoso"). En contraste, esta repetición primero intentará igualar la menor cantidad posible de repeticiones, y cuando esto no funciona y tienen que retroceder, comienzan a emparejar un reptil más a la vez. Como resultado, cuando finalmente ocurre una coincidencia, una repetición reacia coincidiría con la menor cantidad posible de repeticiones.Referencias
Ejemplo 1: de la A a la Z
Comparemos estos dos patrones:
A.*Z
yA.*?Z
.Dada la siguiente entrada:
Los patrones producen las siguientes coincidencias:
A.*Z
produce 1 partido:AiiZuuuuAoooZ
( ver en rubular.com )A.*?Z
produce 2 coincidencias:AiiZ
yAoooZ
( ver en rubular.com )Primero centrémonos en lo que
A.*Z
hace. Cuando coincide con el primeroA
, el.*
, siendo codicioso, primero intenta igualar tantos.
como sea posible.Como
Z
no coincide, el motor retrocede, y.*
luego debe coincidir con uno menos.
:Esto sucede algunas veces más, hasta que finalmente llegamos a esto:
Ahora
Z
puede coincidir, por lo que el patrón general coincide:Por el contrario, la repetición reacia en los
A.*?Z
primeros partidos lo menos.
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 coincidieron los dos patrones:
Ejemplo: una alternativa
En muchas aplicaciones, las dos coincidencias en la entrada anterior es lo que se desea, por lo tanto,
.*?
se utiliza un reacio en lugar del codicioso.*
para evitar la coincidencia excesiva. Sin embargo, para este patrón en particular, existe una alternativa mejor, utilizando la clase de caracteres negados.El patrón
A[^Z]*Z
también encuentra las mismas dos coincidencias que elA.*?Z
patrón para la entrada anterior ( como se ve en ideone.com ).[^Z]
es lo que se llama una clase de caracteres negados : coincide con cualquier cosa menosZ
.La principal diferencia entre los dos patrones está en el rendimiento: al ser más estricta, la clase de caracteres negados solo puede coincidir en un sentido para una entrada determinada. No importa si usa un modificador codicioso o reacio para este patrón. De hecho, en algunos sabores, puedes hacerlo aún mejor y usar lo que se llama cuantificador posesivo, que no retrocede en absoluto.
Referencias
Ejemplo 2: de A a ZZ
Este ejemplo debería ser ilustrativo: muestra cómo los patrones de clase de caracteres codiciosos, renuentes y negados coinciden de manera diferente dada la misma entrada.
Estas son las coincidencias para la entrada anterior:
A[^Z]*ZZ
produce 1 coincidencia:AuuZZ
( como se ve en ideone.com )A.*?ZZ
produce 1 coincidencia:AiiZooAuuZZ
( como se ve en ideone.com )A.*ZZ
produce 1 coincidencia:AiiZooAuuZZeeeZZ
( como se ve en ideone.com )Aquí hay una representación visual de lo que coincidieron:
Temas relacionados
Estos son enlaces a preguntas y respuestas en stackoverflow que cubren algunos temas que pueden ser de interés.
Una repetición codiciosa puede superar a otra
fuente
Digamos que tienes:
<(.*)>
coincidiríaa></a
donde<(.*?)>
coincidiríaa
. Este último se detiene después del primer partido de>
. Comprueba una o 0 coincidencias de.*
seguido por la siguiente expresión.La primera expresión
<(.*)>
no se detiene cuando coincide con la primera>
. Continuará hasta el último partido de>
.fuente