Existe-t-il un moyen rapide de trouver chaque correspondance d'une expression régulière dans Ruby? J'ai parcouru l'objet Regex dans la Ruby STL et cherché sur Google en vain.
Existe-t-il un moyen rapide de trouver chaque correspondance d'une expression régulière dans Ruby? J'ai parcouru l'objet Regex dans la Ruby STL et cherché sur Google en vain.
Réponses:
L'utilisation scan
devrait faire l'affaire:
string.scan(/regex/)
/(?=(...))/
.
Pour trouver toutes les chaînes correspondantes, utilisez la scan
méthode String .
str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]
Si vous le souhaitez, MatchData
qui est le type de l'objet renvoyé par la match
méthode Regexp , utilisez:
str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]
L'avantage d'utiliser MatchData
est que vous pouvez utiliser des méthodes telles que offset
:
match_datas = str.to_enum(:scan, /\d+/).map { Regexp.last_match }
match_datas[0].offset(0)
#=> [2, 4]
match_datas[1].offset(0)
#=> [7, 8]
Consultez ces questions si vous souhaitez en savoir plus:
La lecture sur les variables spéciales $&
, $'
, $1
, $2
Ruby sera utile aussi.
si vous avez une expression rationnelle avec des groupes:
str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/
vous pouvez utiliser la scan
méthode de String pour trouver des groupes correspondants:
str.scan re
#> [["54"], ["1"], ["3"]]
Pour trouver le motif correspondant:
str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]
est plus idiomatique questr.to_enum(:scan,re).map {$&}
/(\d+)[m-t]/
ne pas /\d+[m-t]/
écrire: re = /(\d+)[m-t]/; str.scan(re)
c'est la même chose str.scan(/(\d+)[mt]/)
mais j'obtiens #> [["" 54 "], [" 1 "], [" 3 "]]
et non "54m", "1t", "3r"]
La question était: si j'ai une expression régulière avec un groupe et que je veux capturer tous les modèles sans changer le régulier expression (quitter le groupe), comment faire? En ce sens, une solution possible, quoique un peu cryptique et difficile à lire, était:str.to_enum(:scan,re).map {$&}
Vous pouvez utiliser string.scan(your_regex).flatten
. Si votre expression régulière contient des groupes, elle reviendra dans un seul tableau simple.
string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]
Regex peut également être un groupe nommé.
string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten
Vous pouvez également utiliser gsub
, c'est juste une autre façon si vous voulez MatchData.
str.gsub(/\d/).map{ Regexp.last_match }
your_regex = /(\d+)[m-t]/
et vous n'aurez pas besoin de l'utiliser flatten
. Votre dernier exemple utilise last_match
qui, dans ce cas, est probablement sûr, mais est global et pourrait éventuellement être écrasé si une expression rationnelle était mise en correspondance avant l'appel last_match
. Au lieu de cela, il est probablement plus sûr à utiliser string.match(regex).captures # => ["group_photo", "jpg"]
ou string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]
comme indiqué dans d'autres réponses, selon le modèle et les besoins.