¿Qué significa “perezoso” y “codicioso” en el contexto de expresiones regulares?

¿Podría alguien explicar estos dos términos de una manera comprensible?

Codicioso consumirá tanto como sea posible. Desde http://www.regular-expressions.info/repeat.html vemos el ejemplo de tratar de unir las tags HTML con <.+> . Supongamos que tiene lo siguiente:

 Hello World 

Puede pensar que <.+> ( . Significa cualquier carácter que no sea de nueva línea y + significa uno o más ) solo coincidiría con el y el , cuando en realidad será muy codicioso, y pasará del primer < hasta el último > . Esto significa que coincidirá con Hello World lugar de lo que usted quería.

Haciéndolo perezoso ( <.+?> ) Evitará esto. Al agregar el ? después del + , le pedimos que repita las veces que sea posible , de modo que lo primero > que aparezca es dónde queremos detener el emparejamiento.

Te animo a que descargues RegExr , una gran herramienta que te ayudará a explorar expresiones regulares, la uso todo el tiempo.

‘Codicioso’ significa emparejar la cadena más larga posible.

‘Lazy’ significa hacer coincidir la cadena más corta posible.

Por ejemplo, el codicioso h.+l coincide con 'hell' en 'hello' pero el holgazán h.+?l coincide con 'hel' .

 +-------------------+-----------------+------------------------------+ | Greedy quantifier | Lazy quantifier | Description | +-------------------+-----------------+------------------------------+ | * | *? | Star Quantifier: 0 or more | | + | +? | Plus Quantifier: 1 or more | | ? | ?? | Optional Quantifier: 0 or 1 | | {n} | {n}? | Quantifier: exactly n | | {n,} | {n,}? | Quantifier: n or more | | {n,m} | {n,m}? | Quantifier: between n and m | +-------------------+-----------------+------------------------------+ 

Agrega un ? a un cuantificador para que sea desabrido, es decir, flojo.

Ejemplo:
cadena de prueba: stackoverflow
expresión greged reg : s.*o salida: stackoverflo w
expresión de reg lazy : s.*?o salida: stacko verflow

Codicioso significa que su expresión coincidirá con un grupo lo más grande posible, perezoso significa que coincidirá con el grupo más pequeño posible. Para esta cadena:

 abcdefghijklmc 

y esta expresión:

 a.*c 

Un partido codicioso coincidirá con toda la cadena, y un partido perezoso coincidirá solo con el primer abc .

Por lo que yo sé, la mayoría del motor regex es codicioso por defecto. Agregar un signo de interrogación al final del cuantificador permitirá la coincidencia diferida.

Como @Andre S mencionó en el comentario.

  • Codicioso: sigue buscando hasta que la condición no esté satisfecha.
  • Lazy: deja de buscar una vez que se cumple la condición.

Consulte el ejemplo a continuación para saber qué es codicioso y qué es perezoso.

 import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { public static void main(String args[]){ String money = "100000000999"; String greedyRegex = "100(0*)"; Pattern pattern = Pattern.compile(greedyRegex); Matcher matcher = pattern.matcher(money); while(matcher.find()){ System.out.println("I'm greeedy and I want " + matcher.group() + " dollars. This is the most I can get."); } String lazyRegex = "100(0*?)"; pattern = Pattern.compile(lazyRegex); matcher = pattern.matcher(money); while(matcher.find()){ System.out.println("I'm too lazy to get so much money, only " + matcher.group() + " dollars is enough for me"); } } } 

El resultado es:

Estoy ansioso y quiero 100000000 dólares. Esto es lo máximo que puedo obtener.

Soy demasiado vago para obtener tanto dinero, solo 100 dólares son suficientes para mí

Tomado de http://www.regular-expressions.info

Codicia : los cuantificadores codiciosos primero intentan repetir la ficha tantas veces como sea posible, y cede gradualmente las coincidencias a medida que el motor retrocede para encontrar una coincidencia general.

Holgazanería : el cuantificador perezoso primero repite el token las veces que sea necesario y expande gradualmente la coincidencia a medida que el motor retrocede a través de la expresión regular para encontrar una coincidencia general.

De expresión regular

Los cuantificadores estándar en las expresiones regulares son codiciosos, lo que significa que coinciden tanto como pueden, solo devolviendo según sea necesario para que coincida con el rest de la expresión regular.

Al usar un cuantificador perezoso, la expresión intenta la coincidencia mínima primero.

Mejor demostrado por el ejemplo. Cuerda. 192.168.1.1 y una expresión regular codiciosa \ b. + \ B. Podría pensar que esto le daría el primer octeto, pero en realidad coincide con toda la cadena. ¡¡¡POR QUÉ!!! Debido a que. + Es codicioso y un partido codicioso coincide con cada personaje en ‘192.168.1.1’ hasta que llega al final de la cadena. ¡Esto es lo importante! Ahora comienza a retroceder un personaje a la vez hasta que encuentra una coincidencia para el 3er token (\ b).

Si la secuencia de comandos era un archivo de texto de 4 GB y 192.168.1.1 al inicio, podría ver fácilmente cómo este retroceso podría causar un problema.

Para hacer un regex no codicioso (flojo) ponga un signo de interrogación después de su búsqueda codiciosa, por ejemplo *? ?? +? Lo que sucede ahora es el token 2 (¿+?) Encuentra una coincidencia, la expresión regular se mueve a lo largo de un carácter y luego prueba el siguiente token (\ b) en lugar de token 2 (+?). Así que se arrastra con cautela.

Engaño codicioso. El comportamiento predeterminado de las expresiones regulares es ser codicioso. Eso significa que trata de extraer tanto como sea posible hasta que se ajuste a un patrón, incluso cuando una parte más pequeña hubiera sido sintácticamente suficiente.

Ejemplo:

 import re text = "Regex Greedy Matching Example " re.findall('<.*>', text) #> ['Regex Greedy Matching Example '] 

En lugar de coincidir hasta la primera aparición de ‘>’, extrajo toda la cadena. Este es el comportamiento avaricioso predeterminado o ‘tómalo todo’ de regex.

La coincidencia diferida , por otro lado, ‘toma lo menos posible’. Esto se puede efectuar agregando un ? al final del patrón.

Ejemplo:

 re.findall('<.*?>', text) #> ['', ''] 

Si solo desea que se recupere la primera coincidencia, utilice el método de búsqueda en su lugar.

 re.search('<.*?>', text).group() #> '' 

Fuente: ejemplos de Python Regex

Codicioso significa que consumirá su patrón hasta que no quede ninguno y no busque más.

Lazy se detendrá tan pronto como encuentre el primer patrón que solicitó.

Un ejemplo común que a menudo encuentro es \s*-\s*? de una expresión regular ([0-9]{2}\s*-\s*?[0-9]{7})

La primera \s* se clasifica como codiciosa debido a * y se verá tantos espacios blancos como sea posible después de que se encuentren los dígitos y luego buscará un carácter de guión “-“. ¿Dónde está el segundo \s*? es flojo por el presente de *? lo que significa que se verá el primer carácter de espacio en blanco y se detendrá allí mismo.

trata de entender el siguiente comportamiento:

  var input = "0014.2"; Regex r1 = new Regex("\\d+.{0,1}\\d+"); Regex r2 = new Regex("\\d*.{0,1}\\d*"); Console.WriteLine(r1.Match(input).Value); // "0014.2" Console.WriteLine(r2.Match(input).Value); // "0014.2" input = " 0014.2"; Console.WriteLine(r1.Match(input).Value); // "0014.2" Console.WriteLine(r2.Match(input).Value); // " 0014" input = " 0014.2"; Console.WriteLine(r1.Match(input).Value); // "0014.2" Console.WriteLine(r2.Match(input).Value); // "" 
    Intereting Posts