Points d'interrogation dans les expressions régulières
Je lis la référencedes expressions régulières et je pense à ? et ?? caractère. Pourriez-vous m'expliquer avec quelques exemples de leur utilité? Je ne les comprends pas assez.
Merci
4 réponses
La clé de La différence entre ?
et ??
leur paresse. ??
est paresseux, ?
ne l'est pas.
Disons que vous voulez rechercher le mot " voiture "dans un corps de texte, mais vous ne voulez pas être limité au singulier" voiture"; vous voulez aussi correspondre au pluriel"voitures".
Voici un exemple de phrase:
I own three cars.
Maintenant, si je voulais correspondre le mot "voiture" et je ne voulais obtenir la chaîne de caractères "voiture" en retour, je voudrais utiliser le paresseux ??
comme ceci:
cars??
Cela dit: "Cherchez le mot voiture ou voitures; si vous trouvez l'un ou l'autre, retournez car
et rien de plus".
Maintenant, si je voulais match contre les mêmes mots ("voiture" ou "voitures") et je voulais avoir l'ensemble du match, en retour, , j'aimerais utiliser la non-lazy ?
comme ceci:
cars?
Ceci dit, "Cherchez le mot voiture ou voitures, et retournez soit voiture ou Voitures, Tout ce que vous trouvez".
Dans le monde de l'informatique programmation, paresseux signifie généralement "évaluer seulement autant que nécessaire". Donc, le lazy ??
ne renvoie que ce qui est nécessaire pour faire une correspondance; puisque le " S "dans" cars " est facultatif, ne le renvoyez pas. D'un autre côté, les opérations non paresseuses (parfois appelées greedy ) évaluent autant que possible, d'où le ?
renvoie toute la correspondance, y compris le "s"facultatif.
Personnellement, je me retrouve à utiliser {[1] } comme un moyen de rendre d'autres opérateurs d'expressions régulières paresseux (comme le *
et +
opérateurs) plus souvent que je l'utilise pour une option de caractère simple, mais YMMV.
Voir dans le Code
Voici ce qui précède implémenté dans Clojure à titre d'exemple:
(re-find #"cars??" "I own three cars.")
;=> "car"
(re-find #"cars?" "I own three cars.")
;=> "cars"
L'élément re-find
est une fonction qui prend son premier argument comme une expression régulière #"cars??"
et renvoie le premier match qu'il trouve dans la deuxième argument "I own three cars."
C'est une excellente question, et il m'a fallu un certain temps pour voir le point du quantificateur paresseux ??
moi-même.
? - Facultatif (gourmand) quantificateur
L'utilité de ?
est assez facile à comprendre. Si vous vouliez trouver à la fois http
et https
, vous pouvez utiliser un modèle comme ceci:
https?
Ce modèle correspond aux deux entrées, car il rend le s
facultatif.
?? - Facultatif (paresseux) quantificateur
??
est plus subtile. Habituellement, il fait la même chose ?
ne. Cela ne change pas le résultat true/false lorsque vous demandez: "cette entrée Satisfait-elle cette expression rationnelle?" au lieu de cela, c'est pertinent à la question: " quelle partie de cette entrée correspond à cette expression rationnelle, et quelles parties appartiennent à quels groupes?" si une entrée peut satisfaire le modèle de plus d'une manière, le moteur décidera comment le regrouper en fonction de ?
vs. ??
(ou *
vs. *?
, ou +
vs. +?
).
Dites que vous avez un ensemble d'entrées que vous voulez valider et analyser. Voici un exemple (certes idiot):
Input:
http123
https456
httpsomething
Expected result:
Pass/Fail Group 1 Group 2
Pass http 123
Pass https 456
Pass http something
Vous essayez la première chose qui vient à l'esprit, qui est ce:
^(http)([a-z\d]+)$
Pass/Fail Group 1 Group 2 Grouped correctly?
Pass http 123 Yes
Pass http s456 No
Pass http something Yes
Ils passent tous, mais vous ne pouvez pas utiliser le deuxième ensemble de résultats parce que vous ne vouliez que 456
dans le Groupe 2.
Très bien, essayonsà nouveau . Disons que le Groupe 2 peut être des lettres ou des chiffres, mais pas les deux:
(https?)([a-z]+|\d+)
Pass/Fail Group 1 Group 2 Grouped correctly?
Pass http 123 Yes
Pass https 456 Yes
Pass https omething No
Maintenant, la deuxième entrée est correcte, mais la troisième est mal groupée car {[9] } est gourmand par défaut (le +
l'est aussi, mais le {[9] } est arrivé en premier). Au moment de décider si le s
fait partie de https?
ou [a-z]+|\d+
, si le résultat est une passe de toute façon, le moteur regex choisira toujours celui de gauche. Donc, le Groupe 2 perd s
parce que le Groupe 1 l'a aspiré.
Pour résoudre ce problème, vous faites un petit changement :
(https??)([a-z]+|\d+)$
Pass/Fail Group 1 Group 2 Grouped correctly?
Pass http 123 Yes
Pass https 456 Yes
Pass http something Yes
Essentiellement, cela signifie: "Match https
si vous devez, mais voir si cela passe encore lorsque le Groupe 1 est juste http
." Le moteur se rend compte que le s
pourrait fonctionner dans le cadre de [a-z]+|\d+
, il préfère donc le mettre dans le Groupe 2.
?
rend simplement l'élément précédent (caractère, classe de caractères, groupe) facultatif:
colou?r
Correspond à " couleur "et"couleur"
(swimming )?pool
Correspond à "une piscine "et"la piscine"
??
est le même, mais il est aussi paresseux, l'élément sera être exclus si possible. Comme le notent ces docs, ?? est rare dans la pratique. Je ne l'ai jamais utilisé.
Quelques autres utilisations des Points d'interrogation dans les expressions régulières
En dehors de ce qui est expliqué dans d'autres réponses, Il y a encore 3 autres utilisations de points d'interrogation dans les expressions régulières.
-
Anticipation Négatif
Les lookaheads négatifs sont utilisés si vous voulez faites correspondre quelque chose qui n'est pas suivi d'autre chose. Négatif anticipation de construire est la paire de parenthèses, avec l'ouverture parenthèse suivie d'un point d'interrogation et un point d'exclamation.
x(?!x2)
exemple
- considérez un mot
There
-
Maintenant, par défaut, la RegEx
e
trouverez la troisième lettree
dans wordThere
.There ^
-
Cependant, si vous ne voulez pas le {[7] } qui est immédiatement suivi de
r
, alors vous pouvez utiliser RegExe(?!r)
. Maintenant, le résultat serait:There ^
- considérez un mot
-
Anticipation Positif
Lookahead positif fonctionne juste la même.
q(?=u)
correspond à unq
qui est immédiatement suivie d'unu
, sans que lau
fasse partie de la correspondre. La construction positive lookahead est une paire de parenthèses, avec la parenthèse d'ouverture suivie d'un point d'interrogation et d'un signe égal.exemple
- considérez un mot
getting
-
Maintenant, par défaut, la RegEx
t
trouverez la troisième lettret
dans wordgetting
.getting ^
-
Cependant, si vous voulez le {[18] } qui est immédiatement suivi de
i
, alors vous pouvez utiliser RegExt(?=i)
. Maintenant, le résultat serait:getting ^
- considérez un mot
-
Groupes Non-Capture
Chaque fois que vous placez une Expression régulière entre parenthèses
()
, ils créez un groupe de capture numéroté. Il stocke la partie de la chaîne correspond à la partie de l'expression régulière à l'intérieur du parenthèse.Si vous n'avez pas besoin du groupe pour capturer sa correspondance, vous pouvez optimiser cette réguliers expression dans
(?:Value)