Réponses:
Les gourmands consommeront autant que possible. De http://www.regular-expressions.info/repeat.html nous voyons l'exemple d'essayer de faire correspondre les balises HTML avec <.+>
. Supposons que vous ayez les éléments suivants:
<em>Hello World</em>
Vous pouvez penser que <.+>
( .
signifie n'importe quel caractère non nouveau et +
signifie un ou plusieurs ) ne correspondrait qu'au <em>
et au </em>
, alors qu'en réalité il sera très gourmand et ira du premier <
au dernier >
. Cela signifie qu'il correspondra à la <em>Hello World</em>
place de ce que vous vouliez.
Le rendre paresseux ( <.+?>
) empêchera cela. En ajoutant l' ?
after the +
, nous lui disons de répéter le moins de fois possible , donc la première fois >
qu'il apparaît, c'est là 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.
<[^>]+>
regex101.com/r/lW0cY6/1
«Gourmand» signifie correspondre à la chaîne la plus longue possible.
«Paresseux» signifie correspondre à la chaîne la plus courte possible.
Par exemple, les avides h.+l
matchs 'hell'
dans 'hello'
mais les paresseux h.+?l
matchs 'hel'
.
h.+l
matchs 'helol'
dans 'helolo'
mais les paresseux h.+?l
matchs 'hel'
.
x?
Moyen x
est facultatif mais +?
est une syntaxe différente. Cela signifie cesser de chercher après avoir trouvé quelque chose qui correspond - une correspondance paresseuse.
?
signifie facultatif et+?
signifie paresseux. Le \+?
moyen +
est donc facultatif.
+-------------------+-----------------+------------------------------+
| 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 indigne, c'est-à-dire paresseux.
Exemple:
chaîne de test: expression de reg glouton stackoverflow :
s.*o
sortie: stackoverflo w
expression de reg paresseux : s.*?o
sortie: stacko verflow
re.match('(f)?(.*)', 'food').groups()
à re.match('(f)??(.*)', 'food').groups()
. Dans ce dernier, (f)??
ne correspondra pas au «f» de tête, même s'il le pourrait. Par conséquent, le «f» sera mis en correspondance avec le deuxième groupe de capture «. *». Je suis sûr que vous pouvez construire un exemple avec '{n}?' aussi. Certes, ces deux-là sont très rarement utilisés.
Gourmand signifie que votre expression correspondra au plus grand groupe possible, paresseux signifie qu'il correspondra au plus petit groupe possible. Pour cette chaîne:
abcdefghijklmc
et cette expression:
a.*c
Un match gourmand correspondra à toute la chaîne et un match paresseux ne correspondra qu'à la première abc
.
Pour autant que je sache, la plupart des moteurs d'expression régulière sont gourmands par défaut. Ajouter un point d'interrogation à la fin du quantificateur permettra une correspondance paresseuse.
Comme @Andre S l'a mentionné dans le commentaire.
Reportez-vous à l'exemple ci-dessous pour savoir 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");
}
}
}
I'm greeedy and I want 100000000 dollars. This is the most I can get.
I'm too lazy to get so much money, only 100 dollars is enough for me
Tiré de www.regular-expressions.info
Gourmandise : les quantificateurs gourmands essaient d' abord de répéter le jeton autant de fois que possible, et abandonnent progressivement les correspondances à mesure que le moteur revient en arrière pour trouver une correspondance globale.
Paresse : le quantificateur paresseux répète d'abord le jeton aussi peu de fois que nécessaire, et étend progressivement la correspondance au fur et à mesure que le moteur revient sur l'expression régulière pour trouver une correspondance globale.
De l' 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 donnant en retour que nécessaire pour correspondre au reste de l'expression régulière.
En utilisant un quantificateur paresseux, l'expression essaie d'abord la correspondance minimale.
Correspondance gourmande. Le comportement par défaut des expressions régulières est d'être gourmand. Cela signifie qu'il essaie d'extraire autant que possible jusqu'à ce qu'il soit conforme à un modèle, même si une plus petite partie 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 de correspondre jusqu'à la première occurrence de '>', il a extrait la chaîne entière. C'est le comportement par défaut gourmand ou «tout prendre» de l'expression régulière.
L'appariement paresseux , en revanche, «prend le moins possible». Cela 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 Python Regex
Gourmand signifie qu'il consommera votre modèle jusqu'à ce qu'il n'en reste plus et qu'il ne puisse pas chercher plus loin.
Lazy s'arrêtera dès qu'il rencontrera le premier motif que vous avez demandé.
Un exemple courant que je rencontre souvent est celui \s*-\s*?
d'une expression régulière([0-9]{2}\s*-\s*?[0-9]{7})
Le premier \s*
est classé comme gourmand à cause de *
et cherchera autant d'espaces blancs que possible une fois les chiffres rencontrés, puis recherchera un tiret "-". Alors que le second \s*?
est paresseux à cause du présent *?
qui signifie qu'il regardera le premier caractère d'espace blanc et s'arrêtera juste là.
Mieux montré par l'exemple. Chaîne. 192.168.1.1
et un regex gourmand \b.+\b
Vous pourriez penser que cela vous donnerait le 1er octet mais correspond en fait à la chaîne entière. Pourquoi? Parce que le. + Est gourmand et qu'une correspondance gourmande correspond à chaque caractère 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 personnage à la fois jusqu'à ce qu'il trouve une correspondance pour le 3e jeton (\b
).
Si la chaîne un fichier texte de 4 Go et 192.168.1.1 était au début, vous pouvez facilement voir comment ce retour en arrière pourrait causer un problème.
Pour rendre un regex non gourmand (paresseux) mettez un point d'interrogation après votre recherche gourmande par exemple
*?
??
+?
Ce qui se passe maintenant, c'est que le jeton 2 ( +?
) trouve une correspondance, l'expression régulière se déplace le long d'un personnage, puis essaie le prochain jeton ( \b
) plutôt que le jeton 2 ( +?
). Alors, ça avance avec précaution.
S'il est là, ils viendront le prendre. Ils vont tout prendre:
Par exemple, l'IRS correspond à cette expression régulière: .*
$50,000
- L'IRS prendra tout. Ces .*{4}?
ers gourmands
Voir ici pour un exemple: regexr.com/4t27f
D'un autre côté, si je demande un remboursement d'impôt, l'IRS devient soudainement non gourmand, et ils utilisent ce quantificateur:
(.{2}?)([0-9]*)
contre cette expression: $50,000
Le premier groupe n'est pas dans le besoin et ne correspond qu'à $5
- donc je reçois un $5
remboursement. Le reste est pris par l'oncle Sam pour être gaspillé.
Voir ici: Exemple non gourmand .
Cela devient important si vous essayez de faire correspondre certaines parties d'une expression. Parfois, vous ne voulez pas tout faire correspondre.
essayez de comprendre le comportement suivant:
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); // ""