web-dev-qa-db-fra.com

Que signifient "paresseux" et "gourmand" dans le contexte des expressions régulières?

Quelqu'un pourrait-il expliquer ces deux termes de manière compréhensible?

447
ajsie

Gourmand va consommer autant que possible. De http://www.regular-expressions.info/repeat.html , nous voyons l'exemple de la tentative de correspondance des balises HTML avec <.+>. Supposons que vous ayez les éléments suivants:

<em>Hello World</em>

Vous pouvez penser que <.+> (. signifie tout caractère autre que de nouvelle ligne et + signifie un ou plusieurs ) correspondraient seulement au <em> et au </em>, alors qu'en réalité ce sera très gourmand et partira du premier < jusqu'au dernier >. Cela signifie que cela correspondra à <em>Hello World</em> au lieu de ce que vous vouliez.

Rendre cela paresseux (<.+?>) vous évitera cela. En ajoutant le ? après le +, nous lui demandons de répéter le moins de fois possible , donc le premier > il est évident que nous voulons arrêter la correspondance.

Je vous encourage à télécharger RegExr , un excellent outil qui vous aidera à explorer les expressions régulières - je l'utilise tout le temps.

563
Sampson

'Greedy' signifie faire correspondre la chaîne la plus longue possible.

'Lazy' signifie faire correspondre la chaîne la plus courte possible.

Par exemple, le gourmand h.+l correspond à 'hell' dans 'hello' mais le paresseux h.+?l correspond à 'hel'.

269
slebetman
_+-------------------+-----------------+------------------------------+
| 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  |
+-------------------+-----------------+------------------------------+
_

Ajouter un ? à un quantificateur pour le rendre désagréable, c'est-à-dire paresseux.

Exemple:
chaîne de test: stackoverflow
expression de registre glouton : s.*o sortie: stackoverflo w
expression reg paresseuse : s.*?o sortie: stacko verflow

89
Premraj

Gourmand signifie que votre expression correspondra à un groupe aussi grand que possible, paresseux signifie qu'elle correspondra au groupe le plus petit possible. Pour cette chaîne:

abcdefghijklmc

et cette expression:

a.*c

Une correspondance gourmande correspondra à la chaîne entière et une correspondance paresseuse ne concernera que le premier abc.

50
Carl Norum

Autant que je sache, le moteur de la plupart des regex est gourmand par défaut. Ajouter un point d'interrogation à la fin du quantificateur activera la correspondance différée.

Comme @Andre S mentionné dans le commentaire.

  • Greedy: Continuez à chercher jusqu'à ce que la condition ne soit pas satisfaite.
  • Paresseux: arrêtez de chercher une fois que la condition est remplie.

Reportez-vous à l'exemple ci-dessous pour ce qui est gourmand et ce qui est paresseux.

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");
        }
    }
}

Je suis greeedy et je veux 100000000 dollars. C'est le maximum que je puisse obtenir.

Je suis trop paresseux pour avoir autant d'argent, seulement 100 dollars me suffisent

13
Gearon

Tiré de www.regular-expressions.info

Gourmandise : les quantificateurs gloutons tentent d’abord de répéter le jeton autant de fois que possible, puis abandonnent progressivement les correspondances à mesure que le moteur effectue un retour arrière pour trouver une correspondance globale.

Paresse : le quantificateur paresseux répète le jeton aussi peu de fois que nécessaire, puis agrandit progressivement la correspondance lorsque le moteur fait un retour en arrière pour trouver une correspondance globale.

De expression régulière

Les quantificateurs standard dans les expressions régulières sont gourmands, ce qui signifie qu'ils correspondent autant qu'ils le peuvent, ne rendant que ce qui est nécessaire pour correspondre au reste de la regex.

En utilisant un quantificateur paresseux, l'expression essaie d'abord la correspondance minimale.

6
Adriaan Stander

Gourmand signifie qu'il consommera votre motif jusqu'à ce qu'il n'en reste plus et qu'il ne peut plus chercher.

Lazy s'arrêtera dès qu'il rencontrera le premier motif demandé.

Un exemple courant que je rencontre souvent est \s*-\s*? d'une expression rationnelle ([0-9]{2}\s*-\s*?[0-9]{7})

Le premier \s* est classé comme étant glouton en raison de *. Il recherchera autant d'espaces blancs que possible après la découverte des chiffres, puis recherchera un tiret "-". Là où le second \s*? est paresseux à cause du présent de *?, ce qui signifie qu'il va chercher le premier caractère d'espace blanc et s'arrêter là.

3
Girish Pandey

Meilleur montré par l'exemple. Chaîne. 192.168.1.1 et une expression rationnelle gourmande\b. +\B Vous pourriez penser que cela vous donnerait le 1er octet, mais correspond en réalité à la chaîne entière. POURQUOI!!! Parce que le. + Est gourmand et qu'une correspondance gourmande correspond à chaque caractère de '192.168.1.1' jusqu'à ce qu'il atteigne la fin de la chaîne. C'est le bit important !!! Maintenant, il commence à revenir en arrière un caractère à la fois jusqu'à ce qu'il trouve une correspondance pour le 3ème jeton (\ b).

Si la chaîne contenait un fichier texte de 4 Go et 192.168.1.1 au début, vous pourriez facilement voir en quoi ce retour en arrière causerait un problème.

Pour rendre une regex non gourmande (paresseuse), mettez un point d'interrogation après votre recherche gourmande, par exemple *? ?? +? Que se passe-t-il maintenant si le jeton 2 (+?) Trouve une correspondance, l’expression rationnelle se déplace le long d’un caractère, puis essaie le jeton suivant (\ b) plutôt que le jeton 2 (+?). Donc, il rampe avec précaution.

2
Jason Alcock

Correspondance gloutonne. Le comportement par défaut des expressions régulières consiste à être glouton. Cela signifie qu’il essaie d’extraire autant que possible jusqu’à ce qu’il se conforme à un modèle, même si une partie plus petite aurait été syntaxiquement suffisante.

Exemple:

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

Au lieu d’apparaître jusqu’à la première occurrence de ‘>’, il extrait la chaîne entière. C’est le comportement glouton ou "prendre tout" par défaut de regex.

Correspondance paresseuse , en revanche, ‘prend le moins possible '. Ceci peut être effectué en ajoutant un ? à la fin du motif.

Exemple:

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

Si vous souhaitez que seule la première correspondance soit récupérée, utilisez plutôt la méthode de recherche.

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

Source: Exemples de Regex Python

2
Selva

Si quelqu'un arrive ici à la recherche de ce qui est plus rapide lors de l'analyse syntaxique:

Une idée fausse commune sur les performances des expressions rationnelles est que les quantificateurs paresseux (également appelés non-gourmands, réticents, minimaux ou peu cohérents) sont plus rapides que leurs équivalents gourmands. Ce n'est généralement pas vrai, mais avec un qualificatif important: en pratique, les quantificateurs paresseux sont souvent plus rapides.

Extrait de Badassery Flagrant

1
User_coder