Retourne la première correspondance de Ruby regex


97

Je cherche un moyen d'effectuer une correspondance regex sur une chaîne en Ruby et de la faire court-circuiter lors du premier match.

La chaîne que je traite est longue et d'après ce à quoi elle ressemble, la matchméthode standard ( méthode) traiterait le tout, collecterait chaque correspondance et retournerait un objet MatchData contenant toutes les correspondances.

match = string.match(/regex/)[0].to_s

Réponses:


134

Vous pourriez essayer variableName[/regular expression/]. Voici un exemple de sortie d'irb:

irb(main):003:0> names = "erik kalle johan anders erik kalle johan anders"
=> "erik kalle johan anders erik kalle johan anders"
irb(main):004:0> names[/kalle/]
=> "kalle"

N'est-ce pas faire un match et renvoyer le premier résultat dans les coulisses?
Gishu le

7
Après quelques comparaisons avec des chaînes de différentes longueurs et en regardant la source C, il s'avère que Regex.match court-circuite et ne trouve que la première correspondance.
Daniel Beardsley le

3
Neat, je ne connaissais pas ce raccourci.
Pierre

Existe-t-il de la documentation sur ce raccourci? J'ai cherché haut et bas ce que je pensais être une tâche relativement simple et je n'ai résolu mon problème qu'après avoir trouvé cela. Merci!
dmourati

5
@dmourati Vous pouvez trouver cette fonctionnalité documentée dans la chaîne # [] . Merci d'avoir posé des questions sur le document, car en le lisant, j'ai trouvé l' captureargument - qui vous permet de renvoyer une capture au lieu de la correspondance complète.
slothbear

68

Vous pouvez utiliser []: (qui est comme match)

"foo+account2@gmail.com"[/\+([^@]+)/, 1] # matches capture group 1, i.e. what is inside ()
# => "account2"
"foo+account2@gmail.com"[/\+([^@]+)/]    # matches capture group 0, i.e. the whole match
# => "+account2"

4
meilleure réponse complète
akostadinov

23

Si seule l'existence d'un match est importante, vous pouvez choisir

/regexp/ =~ "string"

Quoi qu'il en soit, matchne devrait renvoyer que le premier appel, tandis que les scanrecherches dans toute la chaîne. Donc si

matchData = "string string".match(/string/)
matchData[0]    # => "string"
matchData[1]    # => nil - it's the first capture group not a second match

8

Je ne sais pas encore si cette fonctionnalité est géniale ou tout simplement totalement folle, mais votre regex peut définir des variables locales.

/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
dollars #=> "3"

(Tiré de http://ruby-doc.org/core-2.1.1/Regexp.html ).


Fonctionnalité géniale! Juste ce dont j'avais besoin
RaphaMex

Attention: cela ne fonctionne que lorsque regex =~ string", not when string = ~ regex`
Christopher Oezbek

2

Une expression régulière (regex) n'est rien d'autre qu'une machine à états finis (FSM).

Un FSM tente de répondre à la question "Cet état est-il possible ou non?"

Il continue d'essayer de faire correspondre un modèle jusqu'à ce qu'une correspondance soit trouvée (succès), ou jusqu'à ce que tous les chemins soient explorés et qu'aucune correspondance n'ait été trouvée (échec).

En cas de succès, la question "Cet état est-il possible ou non?" a reçu une réponse "oui". Par conséquent, aucune autre correspondance n'est nécessaire et l'expression régulière revient.

Voir ceci et ceci pour en savoir plus.

De plus: voici un exemple intéressant pour démontrer le fonctionnement des regex. Ici, une regex est utilisée pour détecter si un nombre donné est premier. Cet exemple est en perl, mais il peut aussi être écrit en ruby.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.