Quelle est la différence entre les deux.*? et.* les expressions régulières?
j'essaie de diviser une chaîne en deux parties en utilisant regex. La chaîne est formatée comme suit:
text to extract<number>
j'ai utilisé (.*?)<
et <(.*?)>
qui fonctionnent bien mais après avoir lu dans regex un peu, je viens de commencer à me demander pourquoi j'ai besoin du ?
dans les expressions. Je l'ai seulement fait comme ça après les avoir trouvés à travers ce site donc je ne suis pas vraiment sûr quelle est la différence.
3 réponses
c'est la différence entre les quantificateurs avides et non avides.
"1519170920 Considérer" l'entrée101000000000100
.
en utilisant 1.*1
, *
est cupide - il va correspondre tout le chemin jusqu'à la fin , puis revenir en arrière jusqu'à ce qu'il puisse correspondre 1
, vous laissant avec 1010000000001
.
.*?
est le non-greedy. *
ne correspondra à rien, mais essaiera de correspondre à des caractères supplémentaires jusqu'à ce qu'il corresponde 1
, correspondant finalement à 101
.
tous les quantificateurs ont un mode non-cupide: .*?
, .+?
, .{2,6}?
, et même .??
.
dans votre cas, un motif similaire pourrait être <([^>]*)>
- correspondant à tout sauf un plus grand-que le signe (à strictement parler, il correspond à zéro ou plusieurs caractères autres que >
entre <
et >
).
Sur gourmand vs non-greedy
la répétition dans regex par défaut est greedy : ils essaient de faire correspondre autant de réps que possible, et quand cela ne fonctionne pas et ils doivent revenir en arrière, ils essaient de faire correspondre un rep de moins à la fois, jusqu'à ce qu'une correspondance de l'ensemble du modèle est trouvée. En conséquence, quand un match se produit finalement, une répétition gourmande correspondrait comme beaucoup reps que possible.
le ?
comme un quantificateur de répétition change ce comportement en non-cupide , également appelé réticent ( en Java ) (et parfois"paresseux"). En revanche, cette répétition va d'abord essayer de faire correspondre comme peu reps que possible, et quand cela ne fonctionne pas et ils doivent revenir en arrière, ils commencent à correspondre un rept de plus par fois. Par conséquent, lorsqu'un match a finalement lieu, une répétition hésitante match comme quelques de répétitions que possible.
Références
exemple 1: de A à Z
comparons ces deux motifs: A.*Z
et A.*?Z
.
étant donné l'entrée suivante:
eeeAiiZuuuuAoooZeeee
Les modèles de rendement de la façon suivante:
-
A.*Z
les rendements 1 match:AiiZuuuuAoooZ
( , voir sur rubular.com ) -
A.*?Z
donne 2 matches:AiiZ
etAoooZ
( , voir sur rubular.com )
concentrons-nous d'abord sur ce que A.*Z
fait. Quand il correspond à la première A
, le .*
, étant cupide, tente d'abord de faire correspondre autant de .
que possible.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
puisque le Z
ne correspond pas, les retours de moteur, et .*
doit alors correspondre à un de moins .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
cela arrive encore quelques fois, jusqu'à ce que nous en arrivions finalement à ceci:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
maintenant Z
peut correspondre, donc le modèle général correspond:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
en revanche, la répétition hésitante dans A.*?Z
correspond d'abord à peu de .
que possible, et puis prendre plus de .
si nécessaire. Cela explique pourquoi il trouve deux correspondances dans l'entrée.
Voici une représentation visuelle de ce que les deux motifs correspondaient:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
exemple: une alternative
dans de nombreuses applications, les deux correspondances dans l'entrée ci-dessus c'est ce que l'on souhaite, donc un .*?
réticent est utilisé à la place de l'avide .*
pour éviter l'accumulation. Pour ce motif particulier, cependant, il y a une meilleure alternative, en utilisant la classe de caractères niés.
le motif A[^Z]*Z
trouve aussi les deux mêmes correspondances que le motif A.*?Z
pour l'entrée ci-dessus ( comme vu sur ideone.com ). [^Z]
est ce qu'on appelle une classe de caractères niés : il correspond à tout sauf Z
.
la principale différence entre les deux modèles est dans la performance: étant plus stricte, la classe de caractères niés ne peut correspondre qu'à une seule façon pour une entrée donnée. Cela n'a pas d'importance si vous utilisez des modificateurs Gourmands ou réticents pour ce motif. En fait, dans certaines saveurs, vous pouvez faire encore mieux et utiliser ce qui est appelé quantificateur possessif, qui ne recule pas du tout.
Références
- regular-expressions.info/Repetition -une Alternative à la paresse , classes de caractères niés et quantificateurs possessifs
exemple 2: de A à ZZ
cet exemple devrait être illustratif: il montre comment les modèles de classe de caractères avides, réticents, et niés correspondent différemment étant donné la même entrée.
eeAiiZooAuuZZeeeZZfff
ce sont les correspondances pour l'entrée ci-dessus:
-
A[^Z]*ZZ
les rendements 1 match:AuuZZ
( comme on le voit sur ideone.com ) -
A.*?ZZ
les rendements 1 match:AiiZooAuuZZ
( comme on le voit sur ideone.com ) -
A.*ZZ
les rendements 1 match:AiiZooAuuZZeeeZZ
( comme on le voit sur ideone.com )
Voici une représentation visuelle de ce qu'ils correspondaient:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
rubriques Connexes
il s'agit de liens vers des questions et des réponses sur stackoverflow qui couvrent certains sujets qui peuvent être d'intérêt.
Une gourmande de répétition peut outgreed l'autre
disons que vous avez:
<a></a>
<(.*)>
correspondrait à a></a
où <(.*?)>
correspondrait à a
.
Ce dernier s'arrête après le premier match de >
. Il vérifie la présence d'une
ou 0 correspondances de .*
suivies de l'expression suivante.
la première expression <(.*)>
ne s'arrête pas à la première >
. Elle se poursuivra jusqu'au dernier match de >
.