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

我知道我可以编写一个 Ruby case 语句来检查与正则表达式的匹配。 但是,我想在返回语句中使用匹配数据:

foo = "10/10/2011"


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

我怎么才能做到呢?

谢谢!


注意: 我知道对于上面的简单情况我不会使用 switch 语句,但这只是一个例子。实际上,我试图实现的是对日期的许多潜在正则表达式进行匹配,这些表达式可以用不同的方式编写,然后使用 Ruby 的 Date 类对其进行相应的解析。

44671 次浏览

The references to the latest regex matching groups are always stored in pseudo variables $1 to $9:

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

You can also use the $LAST_MATCH_INFO pseudo variable to get at the whole MatchData object. This can be useful when using named captures:

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

Here's an alternative approach that gets you the same result but doesn't use a switch. If you put your regular expressions in an array, you could do something like this:

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

Declaring m outside the block allows it to still be available after find is done with the block and find will stop as soon as the block returns a true value so you get the same shortcutting behavior that a switch gives you. This gives you the full MatchData if you need it (perhaps you want to use named capture groups in your regexes) and nicely separates your regexes from your search logic (which may or may not yield clearer code), you could even load your regexes from a config file or choose which set of them you wanted at run time.