返回匹配的可选模式

时间:2017-11-23 15:15:50

标签: ruby regex

我想知道如何才能获得匹配正则表达式中的哪种模式。

我有这个正则表达式(我在Ruby中使用.match):

(?i)(penalty is\W+[0-9]+\W+night)|(penalty of\W+[0-9]+\W+)

现在我知道如何在字符串中返回匹配的文本,但是有没有办法为该字符串获取匹配的字符串和匹配的模式?所以我将得到两个结果:

  1. 字符串中匹配的文字:惩罚是1晚
  2. 匹配的模式:(惩罚是\ W + [0-9] + \ W + night)
  3. 最好的问候。

3 个答案:

答案 0 :(得分:3)

pattern = /(?i)(penalty is\W+[0-9]+\W+night)|(penalty of\W+[0-9]+\W+)/

"penalty of 123 points".match(pattern)
=> #<MatchData "penalty of 123 " 1:nil 2:"penalty of 123 ">

非零捕获数显示模式的哪个部分匹配。您可以通过多种方式获取此值,例如:

"penalty of 123 points".match(pattern).captures
=> [nil, "penalty of 123 "]

# Get the index of the first *non-nil* element:
"penalty of 123 points".match(pattern).captures.find_index(&:itself)
=> 1

因此,根据上述方法链是返回0还是1,您将知道第一组或第二组是否匹配。

如果您希望使此代码更透明(更容易理解其工作原理),您还可以考虑使用命名的捕获组,例如:

pattern = /(?i)(?<night>penalty is\W+[0-9]+\W+night)|(?<other>penalty of\W+[0-9]+\W+)/

"penalty of 123 points".match(pattern)
=> #<MatchData "penalty of 123 " night:nil other:"penalty of 123 ">

"penalty of 123 points".match(pattern).named_captures
=> {"night"=>nil, "other"=>"penalty of 123 "}

"penalty of 123 points".match(pattern).named_captures.compact.keys.first
=> "other"

为了更进一步,您还可以将每个“子模式”定义为不同的正则表达式以供将来参考,并将它们连接在一起以进行主匹配,例如:

groups = {
  "night" => /(?<night>penalty is\W+[0-9]+\W+night)/i,
  "other" => /(?<other>penalty of\W+[0-9]+\W+)/i
]

pattern = Regexp.union(groups)

match_group_name = "penalty of 123 points".match(pattern).named_captures.compact.keys.first

puts "Pattern that matched: #{groups[match_group_name]}"

答案 1 :(得分:2)

REGEXPS = [
  /(?<first>penalty is\W+[0-9]+\W+night)/i,
  /(?<second>penalty of\W+[0-9]+\W+)/i
].freeze

Regexp.union(REGEXPS) =~ ""
$~.named_captures

答案 2 :(得分:1)

让我们允许任意数量的联合正则表达式,并设计方法以便于测试。

str为字符串,regexes为正则表达式的数组。对于问题中给出的例子,

regexes = [/(?i)(?<night>penalty is\W+[0-9]+\W+night)/,
           /(?i)(?<other>penalty of\W+[0-9]+\W+)/]

def doit(str, regexes)
  regexes.each do |r|
    m = str[r]
    return [r, m] unless m.nil?
  end
  nil
end