Sur gourmand vs non-gourmand
La répétition dans la regex par défaut est gourmand: ils essaient de faire correspondre autant de répétitions que possible, et quand cela ne fonctionne pas et qu'ils ont à faire marche arrière, ils tentent de faire correspondre les moins de rep à la fois, jusqu'à ce qu'un match de l'ensemble du motif est trouvé. En conséquence, lorsqu'un match se passe enfin, une gourmande de répétition correspond comme beaucoup de répétitions que possible.
L' ?
comme une répétition quantificateur change ce comportement en non-gourmand, aussi appelé réticents (par exemple Java) (et parfois "paresseux"). En revanche, cette répétition va d'abord essayer de mettre en ligne quelques répétitions que possible, et quand cela ne fonctionne pas et qu'ils ont à faire marche arrière, ils commencent correspondant à l'un des plus rept un temps. En conséquence, lorsqu'un match se passe enfin, malgré la répétition correspondent que peu de répétitions que possible.
Références
Exemple 1: De A à Z
Nous allons comparer ces deux modèles: A.*Z
et A.*?Z
.
Compte tenu de la manière suivante:
eeeAiiZuuuuAoooZeeee
Les modèles de rendement de la façon suivante:
Nous allons d'abord mettre l'accent sur ce qu' A.*Z
n'. Quand elle correspondait à la première A
, l' .*
, étant gourmand, essaie d'abord de faire correspondre autant .
que possible.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Depuis l' Z
ne correspond pas, le moteur revient, et .*
doit alors correspondre à un de moins .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
Cela se passe un peu plus de temps, jusqu'à ce que finalement nous arrivons à ceci:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
Maintenant, Z
peut correspondre, de sorte que le schéma d'ensemble correspond à:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
En revanche, les réticents de la répétition en A.*?Z
premiers matchs que quelques .
que possible, et en prenant de plus .
que nécessaire. C'est ce qui explique pourquoi il trouve deux matchs dans l'entrée.
Voici une représentation visuelle de ce que les deux modèles correspondants:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
Exemple: Une alternative
Dans de nombreuses applications, les deux matches au-dessus de l'entrée est ce qui est souhaité, donc un peu réticents .*?
est utilisé à la place de la goulue .*
pour prévenir overmatching. Pour ce modèle particulier, cependant, il y a une meilleure alternative, aide nié de la classe de caractères.
Le modèle A[^Z]*Z
retrouve également le même deux matchs à l' A.*?Z
modèle pour la au-dessus de l'entrée (comme on le voit sur ideone.com). [^Z]
est ce qu'on appelle un niée classe de personnage: elle correspond à rien, mais Z
.
La principale différence entre les deux modèles est dans la performance: plus strictes, le caractère niées classe ne peut correspondre à un moyen pour une entrée donnée. Il n'a pas d'importance si vous utilisez avide ou réticents modificateur pour ce modèle. En fait, dans certaines saveurs, vous pouvez faire encore mieux et d'utiliser ce qui est appelé possessif quantificateur, ce qui ne veut pas revenir en arrière à tous.
Références
Exemple 2: De A à Z
Cet exemple devrait être illustratif: il montre comment le gourmand, réticents, et nié le caractère de classe de modèles de match différemment compte tenu de la même entrée.
eeAiiZooAuuZZeeeZZfff
Ce sont les matches au-dessus de l'entrée:
Voici une représentation visuelle de ce qu'ils en correspondance:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
Rubriques connexes
Ce sont des liens vers les questions et réponses sur stackoverflow qui couvrent certains sujets qui peuvent être d'intérêt.
Une gourmande de répétition peut outgreed un autre