我在字符串中每次出现正则表达式都需要MatchData
。这与Match All Occurrences of a Regex中建议的扫描方法不同,因为它只给我一个字符串数组(我需要完整的MatchData,以获取开始和结束信息等)。
input = "abc12def34ghijklmno567pqrs"
numbers = /\d+/
numbers.match input # #<MatchData "12"> (only the first match)
input.scan numbers # ["12", "34", "567"] (all matches, but only the strings)
我怀疑有一些方法我忽略了。建议?
答案 0 :(得分:65)
你想要
"abc12def34ghijklmno567pqrs".to_enum(:scan, /\d+/).map { Regexp.last_match }
给你
[#<MatchData "12">, #<MatchData "34">, #<MatchData "567">]
如你所见,“技巧”是为了获得每个last_match而构建一个枚举器。
答案 1 :(得分:8)
我目前的解决方案是将一个each_match方法添加到Regexp:
class Regexp
def each_match(str)
start = 0
while matchdata = self.match(str, start)
yield matchdata
start = matchdata.end(0)
end
end
end
现在我能做到:
numbers.each_match input do |match|
puts "Found #{match[0]} at #{match.begin(0)} until #{match.end(0)}"
end
告诉我有更好的方法。
答案 2 :(得分:6)
我会把它放在这里以防万一通过相应的谷歌搜索提供代码:
input = "abc12def34ghijklmno567pqrs"
numbers = /\d+/
input.gsub(numbers) { |m| p $~ }
结果如下:
⇒ #<MatchData "12">
⇒ #<MatchData "34">
⇒ #<MatchData "567">
答案 3 :(得分:1)
我很惊讶没有人提到Ruby标准库中包含的令人惊讶的StringScanner类:
require 'strscan'
s = StringScanner.new('abc12def34ghijklmno567pqrs')
while s.skip_until(/\d+/)
num, offset = s.matched.to_i, [s.pos - s.matched_size, s.pos - 1]
# ..
end
不,它没有为您提供MatchData对象,但它确实为您提供了一个基于索引的字符串接口。
答案 4 :(得分:0)
input = "abc12def34ghijklmno567pqrs"
n = Regexp.new("\\d+")
[n.match(input)].tap { |a| a << n.match(input,a.last().end(0)+1) until a.last().nil? }[0..-2]
=> [#<MatchData "12">, #<MatchData "34">, #<MatchData "567">]