如何在字符串中创建多个正则表达式的有序匹配列表?

时间:2011-06-12 05:06:35

标签: ruby regex

如何从多个不同的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"}]

2 个答案:

答案 0 :(得分:3)

您可以使用Regexp.union将所有正则表达式转换为一个正则表达式,然后使用String#scan查找所有匹配项。 scan返回的数组将按匹配位置排序。

答案 1 :(得分:0)

injectcase语句执行恕我直言时,这似乎非常复杂:

> %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