Answers:
使用scan
应该可以解决问题:
string.scan(/regex/)
/(?=(...))/
。
要查找所有匹配的字符串,请使用String的scan
方法。
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]/
您可以使用String的scan
方法来查找匹配的组:
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"]
按照其他答案所示可能更安全。