J'essaie actuellement de rexp une chaîne en plusieurs variables. Exemple de chaîne:
ryan_string = "RyanOnRails: This is a test"
Je l'ai associé à cette expression rationnelle, avec 3 groupes:
ryan_group = ryan_string.scan(/(^.*)(:)(.*)/i)
Maintenant, pour accéder à chaque groupe, je dois faire quelque chose comme ceci:
ryan_group[0][0] (first group) RyanOnRails
ryan_group[0][1] (second group) :
ryan_group[0][2] (third group) This is a test
Cela semble assez ridicule et j'ai l'impression que je fais quelque chose de mal. Je pense pouvoir faire quelque chose comme ceci:
g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)
Est-ce possible? Ou y a-t-il un meilleur moyen que ce que je fais?
Vous ne voulez pas scan
pour cela, cela n'a pas beaucoup de sens. Vous pouvez utiliser String#match
Pour renvoyer un objet MatchData
. Vous pouvez ensuite appeler #captures
Pour renvoyer un tableau de captures. Quelque chose comme ça:
#!/usr/bin/env Ruby
string = "RyanOnRails: This is a test"
one, two, three = string.match(/(^.*)(:)(.*)/i).captures
p one #=> "RyanOnRails"
p two #=> ":"
p three #=> " This is a test"
Sachez que si aucune correspondance n'est trouvée, String#match
Renverra zéro, ce qui pourrait fonctionner mieux:
if match = string.match(/(^.*)(:)(.*)/i)
one, two, three = match.captures
end
Bien que scan
ait peu de sens pour cela. Il fait toujours le travail, il vous suffit d’aplatir d’abord le tableau retourné. one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten
Vous pouvez utiliser Match ou = ~, ce qui vous donnerait une seule correspondance et vous pourrez accéder aux données de correspondance de la même manière ou simplement utiliser les variables de correspondance spéciales $ 1, $ 2, $ 3.
Quelque chose comme:
if ryan_string =~ /(^.*)(:)(.*)/i
first = $1
third = $3
end
Vous pouvez nommer vos matchs capturés
string = "RyanOnRails: This is a test"
/(?<one>^.*)(?<two>:)(?<three>.*)/i =~ string
puts one, two, three
Cela ne fonctionne pas si vous inversez l'ordre de chaîne et l'expression régulière.
Vous devez décider si c'est une bonne idée, mais Ruby regexp peut (automagiquement) définir des variables locales pour vous!
Je ne sais pas encore si cette fonctionnalité est géniale ou tout simplement folle, mais votre expression régulière peut définir des variables locales.
ryan_string = "RyanOnRails: This is a test"
/^(?<webframework>.*)(?<colon>:)(?<rest>)/ =~ ryan_string
# This defined three variables for you. Crazy, but true.
webframework # => "RyanOnRails"
puts "W: #{webframework} , C: #{colon}, R: #{rest}"
(Jetez un oeil à http://Ruby-doc.org/core-2.1.1/Regexp.html , recherchez "variable locale").
Remarque: Comme indiqué dans un commentaire, je constate qu'il existe une réponse similaire et antérieure à cette question de @toonsend ( https: //stackoverflow.com/a/21412455 ). Je ne pense pas que je "volais", mais si vous voulez être juste avec les louanges et honorer la première réponse, sentez-vous libre :) J'espère qu'aucun animal n'a été blessé.
scan()
trouvera toutes les correspondances non répétitives de l'expression rationnelle dans votre chaîne. Ainsi, au lieu de renvoyer un tableau de vos groupes comme vous semblez l'attendre, il renvoie un tableau de tableaux.
Il vaut probablement mieux utiliser match()
, puis obtenir le tableau de captures à l'aide de MatchData#captures
:
g1, g2, g3 = ryan_string.match(/(^.*)(:)(.*)/i).captures
Cependant, vous pouvez aussi le faire avec scan()
si vous voulez:
g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)[0]