RubyのRegexp.last_matchのスコープ

ちょっとハマったのでメモ。

Rubyでは正規表現を一致させた結果をRegexp.last_match$~などで取得する。 リファレンスマニュアルでは次のように説明されている。

カレントスコープで最後に行った正規表現マッチのMatchDataオ ブジェクトを返します。

このカレントスコープはレキシカルに、つまりコードの字面上だけで決定される。 正規表現を一致させた後であっても、スコープが異なれば一致させた結果にアクセスすることはできない。

実証コード:

def foo(re)
  re.call                       # ここで正規表現を一致させる
  p Regexp.last_match           # が、外側のスコープの結果は得られない
end

foo(proc{ 'foo' =~ /foo/ })
p Regexp.last_match             # 同じスコープなら結果を得られる

実行結果:

nil
#<MatchData "foo">