Je lis le référence des expressions régulières et j'y pense? et ?? personnages. Pourriez-vous m'expliquer avec quelques exemples leur utilité? Je ne les comprends pas assez.
merci
La principale différence entre ?
et ??
concerne leur paresse. ??
est paresseux, ?
n'est pas.
Supposons que vous vouliez rechercher le mot "voiture" dans un corps de texte, mais que vous ne vouliez pas être limité à la seule "voiture"; vous voulez également faire correspondre le pluriel "voitures".
Voici un exemple de phrase:
I own three cars.
Maintenant, si je voulais faire correspondre le mot "car" et je voulais seulement obtenir la chaîne "car" en retour, j'utiliserais le paresseux ??
ainsi:
cars??
Cela dit, "recherchez la ou les voitures Word; si vous en trouvez une, retournez car
et rien de plus".
Maintenant, si je voulais faire correspondre les mêmes mots ("voiture" ou "voitures") et je voulais obtenir la correspondance entière en retour, j'utiliserais le non-paresseux ?
ainsi:
cars?
Cela dit, "recherchez la ou les voitures Word, et restituez la voiture ou les voitures, quoi que vous trouviez".
Dans le monde de la programmation informatique, paresseux signifie généralement "évaluer seulement autant que nécessaire". Donc, les paresseux ??
ne renvoie que ce qui est nécessaire pour faire une correspondance; puisque le "s" dans "voitures" est facultatif, ne le retournez pas. D'un autre côté, les opérations non paresseuses (parfois appelées gourmandes) évaluent autant que possible, d'où le ?
renvoie la totalité de la correspondance, y compris le "s" facultatif.
Personnellement, je me retrouve avec ?
comme moyen de rendre paresseux d'autres opérateurs d'expression régulière (comme le *
et +
opérateurs) plus souvent que je ne l'utilise pour une simple option de caractère, mais YMMV.
Voici l'exemple ci-dessus implémenté dans Clojure:
(re-find #"cars??" "I own three cars.")
;=> "car"
(re-find #"cars?" "I own three cars.")
;=> "cars"
L'article re-find
est une fonction qui prend son premier argument comme une expression régulière #"cars??"
et renvoie la première correspondance trouvée dans le deuxième argument "I own three cars."
C'est une excellente question, et il m'a fallu un certain temps pour voir l'intérêt du paresseux ??
moi-même quantificateur.
L'utilité de ?
est assez facile à comprendre. Si vous vouliez trouver à la fois http
et https
, vous pouvez utiliser un modèle comme celui-ci:
https?
Ce modèle correspondra aux deux entrées, car il rend le s
facultatif.
??
est plus subtil. Il fait généralement la même chose ?
Est-ce que. Cela ne change pas le résultat vrai/faux lorsque vous demandez: "Cette entrée satisfait-elle cette expression régulière?" Au lieu de cela, elle est pertinente pour 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 plusieurs manières, le Le moteur décidera comment le regrouper en fonction de ?
contre. ??
(ou *
contre. *?
, ou +
contre. +?
).
Supposons que vous ayez un ensemble d'entrées que vous souhaitez valider et analyser. Voici un exemple (certes stupide):
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 vous vient à l'esprit, qui est this :
^(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 réussissent tous, mais vous ne pouvez pas utiliser le deuxième ensemble de résultats, car vous vouliez uniquement 456
dans le groupe 2.
Très bien, réessayez . Disons que le groupe 2 peut être composé de lettres ou de chiffres, mais pas des 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 classée car ?
est gourmand par défaut (le +
l'est aussi, mais le ?
est venu en premier). Pour décider si s
fait partie de https?
ou [a-z]+|\d+
, si le résultat est une passe dans les deux cas, le moteur d'expression régulière 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 effectuez n tout 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 voyez si cela passe quand 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 c'est aussi paresseux, donc l'élément sera sera exclu si possible. Comme le notent ces documents, ?? est rare dans la pratique. Je ne l'ai jamais utilisé.
Outre ce qui est expliqué dans les autres réponses, il y a encore 3 utilisations supplémentaires des points d'interrogation dans les expressions régulières.
Lookahead négatif
Les lookaheads négatifs sont utilisés si vous voulez faire correspondre quelque chose qui n'est pas suivi par autre chose. La construction d'anticipation négative est la paire de parenthèses, avec la parenthèse d'ouverture suivie d'un point d'interrogation et d'un point d'exclamation. x(?!x2)
exemple
There
Désormais, par défaut, le RegEx e
trouvera la troisième lettre e
dans Word There
.
There
^
Cependant, si vous ne voulez pas le e
qui est immédiatement suivi de r
, vous pouvez utiliser RegEx e(?!r)
. Maintenant, le résultat serait:
There
^
Lookahead positif
L'anticipation positive fonctionne tout de même. q(?=u)
correspond à un q
qui est immédiatement suivi d'un u
, sans faire de la partie u
de la correspondance. La construction d'anticipation positive est une paire de parenthèses, avec la parenthèse d'ouverture suivie d'un point d'interrogation et d'un signe égal.
exemple
getting
Désormais, par défaut, le RegEx t
trouvera la troisième lettre t
dans Word getting
.
getting
^
Cependant, si vous voulez le t
qui est immédiatement suivi de i
, vous pouvez utiliser RegEx t(?=i)
. Maintenant, le résultat serait:
getting
^
Groupes non capturants
Chaque fois que vous placez une expression régulière entre parenthèses ()
, Ils créent un groupe de capture numéroté. Il stocke la partie de la chaîne correspondant à la partie de l'expression régulière à l'intérieur des parenthèses.
Si vous n'avez pas besoin que le groupe capture sa correspondance, vous pouvez optimiser cette expression régulière en
(?:Value)