如何从多个不同的Regexp中获取字符串中的匹配列表,并且这些匹配是否按字符串中的位置相对排序?
该字符串可以包含来自同一Regexp的多个匹配项。
根据sepp2k的回答,这是我实施的解决方案(简化示例):
test_data = "
a_word
another_word
23445
12432423
third_word
"
regexps = /(?<word>[a-zA-Z_]+)/, /(?<number>[\d]+)/
words = regexps.map{|re| re.names}.flatten!
matches = []
test_data.scan(Regexp.union(regexps)) do
words.each do |word|
m = Regexp.last_match
matches << {word => m.to_s} if m[word]
end
end
p matches
输出:
[{"word"=>"a_word"}, {"word"=>"another_word"}, {"number"=>"23445"}, {"number"=>"12432423"}, {"word"=>"third_word"}]
答案 0 :(得分:3)
您可以使用Regexp.union
将所有正则表达式转换为一个正则表达式,然后使用String#scan
查找所有匹配项。 scan
返回的数组将按匹配位置排序。
答案 1 :(得分:0)
当inject
和case
语句执行恕我直言时,这似乎非常复杂:
> %w{a_word another_word 23445 12432423 third_word}.inject([]) {|s,v| s << case v when /^[a-zA-Z_]+$/ then {'word' => v} when /^\d+$/ then {'number' => v} end }
=> [{"word"=>"a_word"}, {"word"=>"another_word"}, {"number"=>"23445"}, {"number"=>"12432423"}, {"word"=>"third_word"}]
为了便于阅读,您可以拥有以下内容:
data = <<EOD
a_word
another_word
23445
12432423
third_word
EOD
data.split.inject([]) do |s,v|
s << case v
when /^[a-zA-Z_]+$/
{'word' => v}
when /^\d+$/
{'number' => v}
end
end