Відповіді:
Використання 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"]
Регекс також може бути названою групою.
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"]
як показано в інших відповідях, залежно від структури та потреб.