正規表現と後方参照を使用してRubyswitchステートメント(case…when)を作成するにはどうすればよいですか?


86

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ステートメントを使用しないことを理解していますが、これは1つの例にすぎません。実際、私が達成しようとしているのは、さまざまな方法で記述できる日付の多くの潜在的な正規表現を照合し、それに応じてRubyのDateクラスで解析することです。


1
RubyのDate.parseは、多くの日付形式を理解します。試しましたか?
雨2011

この質問には答えられませんが、クロニックの宝石を見たいと思うかもしれません...
DGM 2011

回答:


153

最新の正規表現一致グループへの参照は、常に次の疑似変数 $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

1
@Yossiスレッドセーフに関するコメントのソースはありますか?私はルビー1.8.7で実験をしましたが、これはスレッドセーフであることを示しているようです。(1秒ごとに正規表現に一致するスレッド-ローカル一致が破壊されているかどうかをirbでチェックします)
Joel

5
-1正規表現に関係する$変数は、その前にドル記号が付いていてもグローバルではありません。
Andrew Grimm 2011

@AndrewGrimmこれを指摘してくれてありがとう。私はそれを知りませんでした。古いコードをたくさん変更する必要があります:-/
Yossi 2011

あなたも行うことができ$1$2...$9またはRegexp.last_match(1)rubocopによって推奨されているように
エドガー・オルテガを

6

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

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

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


このcaseアプローチを使用して、スレッドセーフについても考えていました。ケースアプローチ(?)のグローバル変数ではなく、スレッドシナリオでmuのアプローチを使用したい場合があります
Casper
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.