如何使用正则表达式和反向引用编写Ruby switch语句(case ... when)?

Yuv*_*rmi 80 ruby regex switch-statement

我知道我可以编写一个Ruby case语句来检查正则表达式的匹配.但是,我想在return语句中使用匹配数据.像这样的半伪代码:

foo = "10/10/2011"

case foo
    when /^([0-9][0-9])/
        print "the month is #{match[1]}"
    else
        print "something else"
end
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

谢谢!


请注意:我理解我不会像上面那样对一个简单的情况使用switch语句,但这只是一个例子.实际上,我想要实现的是将许多潜在的正则表达式匹配为可以用各种方式编写的日期,然后相应地使用Ruby的Date类进行解析.

Yos*_*ssi 146

对最新正则表达式匹配组的引用始终存储在伪变量 $1$9:

case foo
when /^([0-9][0-9])/
    print "the month is #{$1}"
else
    print "something else"
end
Run Code Online (Sandbox Code Playgroud)

您还可以使用$LAST_MATCH_INFO伪变量来获取整个MatchData对象.这在使用命名捕获时非常有用:

case foo
when /^(?<number>[0-9][0-9])/
    print "the month is #{$LAST_MATCH_INFO['number']}"
else
    print "something else"
end
Run Code Online (Sandbox Code Playgroud)

  • -1 $与正则表达式相关的变量不是全局的,即使它前面有一个美元符号. (5认同)
  • 您还可以按照 rubocop 的建议执行 `$1`、`$2` ... `$9` 或 `Regexp.last_match(1)` (2认同)

mu *_*ort 6

这是一种替代方法,可让您获得相同的结果,但不使用开关。如果将正则表达式放入数组中,则可以执行以下操作:

res = [ /pat1/, /pat2/, ... ]
m   = nil
res.find { |re| m = foo.match(re) }
# Do what you will with `m` now.
Run Code Online (Sandbox Code Playgroud)

m在该块外部声明之后,它在find完成该块之后仍然可以使用,并且find将在该块返回真值后立即停止,因此您将获得与开关相同的快捷方式行为。MatchData如果需要,这可以为您提供完整的信息(也许您想在正则表达式中使用命名的捕获组),并且可以很好地将正则表达式与搜索逻辑分开(这可能会或可能不会产生更清晰的代码),甚至可以从配置文件或在运行时选择所需的一组。