web-dev-qa-db-ja.com

正規表現と後方参照を含むRuby switchステートメント(case ... when)を記述する方法は?

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

どうすればそれを達成できますか?

ありがとう!


注:上記のような単純なケースではswitchステートメントを使用しないことを理解していますが、これはほんの一例です。現実には、私が達成しようとしているのは、さまざまな方法で記述できる日付の多くの潜在的な正規表現のマッチングであり、それに応じてRubyのDateクラスで解析します。

79
Yuval Karmi

最新の正規表現一致グループへの参照は、常に 疑似変数$1から$9に保存されます。

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

$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
145
Yossi

同じ結果を得るが、スイッチを使用しない代替アプローチを次に示します。正規表現を配列に入れると、次のようなことができます。

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

ブロック外でmを宣言すると、ブロックで find が実行され、 find ブロックがtrue値を返すとすぐに停止し、スイッチが提供するのと同じショートカット動作を取得します。これにより、完全な MatchData が必要な場合(おそらく、正規表現で名前付きキャプチャグループを使用したい場合)、正規表現と検索ロジックをうまく分離できます(そうでない場合もあります)より明確なコードが得られます)、構成ファイルから正規表現をロードしたり、実行時に必要なそれらのセットを選択することもできます。

6
mu is too short