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

31
demandé sur AndersTornkvist 2011-04-07 19:26:49

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

26
répondu semperos 2011-04-07 15:55:08

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.

30
répondu Justin Morgan 2016-01-26 16:36:27

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

11
répondu Matthew Flaschen 2011-04-07 15:33:23

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.    

  1. 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 lettre e dans word There.

      There
        ^
      
    • Cependant, si vous ne voulez pas le {[7] } qui est immédiatement suivi de r, alors vous pouvez utiliser RegEx e(?!r). Maintenant, le résultat serait:

      There
          ^
      
  2. Anticipation Positif

    Lookahead positif fonctionne juste la même. q(?=u) correspond à un q qui est immédiatement suivie d'un u, sans que la u 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 lettre t dans word getting.

      getting
        ^
      
    • Cependant, si vous voulez le {[18] } qui est immédiatement suivi de i, alors vous pouvez utiliser RegEx t(?=i). Maintenant, le résultat serait:

      getting
         ^
      
  3. 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)
    

Voir aussi ce et ce.

7
répondu Raman Sahasi 2017-11-14 15:28:35