web-dev-qa-db-fra.com

Points d'interrogation dans les expressions régulières

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

36
xralf

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.

Voir dans Code

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."

34
semperos

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.

? - Quantificateur optionnel (gourmand)

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.

?? - Quantificateur optionnel (paresseux)

?? 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.

31
Justin Morgan

? 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é.

11
Matthew Flaschen

Quelques autres utilisations des points d'interrogation dans les expressions régulières

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.

  1. 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

    • Considérez un mot 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
          ^
      
  2. 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

    • Considérez un mot 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
         ^
      
  3. 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)
    

Voir aussi this et this .

8
Raman Sahasi