Ответы:
Использование scan
должно сделать трюк:
string.scan(/regex/)
/(?=(...))/
.
Чтобы найти все подходящие строки, используйте scan
метод String .
str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]
Если хотите, то MatchData
есть тип объекта, возвращаемого методом Regexp match
, используйте:
str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]
Преимущество использования MatchData
заключается в том, что вы можете использовать такие методы, как 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]
Посмотрите эти вопросы, если вы хотите узнать больше:
Чтение о специальных переменных $&
, $'
, $1
, $2
в Ruby , будет полезно тоже.
если у вас есть регулярное выражение с группами:
str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/
Вы можете использовать scan
метод String для поиска подходящих групп:
str.scan re
#> [["54"], ["1"], ["3"]]
Чтобы найти соответствующий шаблон:
str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]
более идиоматичен, чемstr.to_enum(:scan,re).map {$&}
/(\d+)[m-t]/
не /\d+[m-t]/
писать: то re = /(\d+)[m-t]/; str.scan(re)
же самое, str.scan(/(\d+)[mt]/)
но я получаю #>, [["" 54 "], [" 1 "], [" 3 "]]
а не "54m", "1t", "3r"]
вопрос: было ли у меня регулярное выражение с группой, и я хочу захватить все шаблоны, не меняя регулярные выражение (выход из группы), как я могу это сделать? В этом смысле возможное решение, хотя и немного загадочное и трудное для чтения, было:str.to_enum(:scan,re).map {$&}
Вы можете использовать string.scan(your_regex).flatten
. Если ваше регулярное выражение содержит группы, оно вернется в виде одного простого массива.
string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]
Regex также может быть именованной группой.
string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten
Вы также можете использовать gsub
, это просто еще один способ, если вы хотите MatchData.
str.gsub(/\d/).map{ Regexp.last_match }
your_regex = /(\d+)[m-t]/
и вам не нужно будет использовать flatten
. Ваш последний пример использует, last_match
который в этом случае, вероятно, является безопасным, но является глобальным и может быть перезаписан, если перед вызовом было найдено какое-либо регулярное выражение last_match
. Вместо этого, вероятно, безопаснее использовать string.match(regex).captures # => ["group_photo", "jpg"]
или, string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]
как показано в других ответах, в зависимости от схемы и потребностей.