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
Daniel Beardsley
la source

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"
Presidenten
la source
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)

"[email protected]"[/\+([^@]+)/, 1] # matches capture group 1, i.e. what is inside ()
# => "account2"
"[email protected]"[/\+([^@]+)/]    # matches capture group 0, i.e. the whole match
# => "+account2"
Benjamin Crouzier
la source
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
Slartibartfast
la source
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 ).

Félix
la source
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.

Tournesol
la source