うまいタイトルが思い付かない。
Ruby は $~ や Regexp.last_match などで、カレントスコープで実行した最後の正規表現マッチの結果を得ることができる。
/(.)(.)/ === 'abcdef' puts $1 # => a puts $2 # => b
こんな風に。
ところで、 Ruby には Enumerable#grep というメソッドがある。コレクションのそれぞれの要素と引数を === 演算子で比較して、 true だった要素を集めた配列を返すメソッド。 === という演算子で比較するので、正規表現に限らず、たいていのオブジェクトで比較することができる。
ただし、 Enumerable#grep はイテレータを使って実装されており、イテレータではブロックローカルなスコープが導入される。つまり、カレントスコープで実行されないので、 Regexp.last_match などでマッチの結果を得ることができない。
では、どうするかというと、ブロックつきで Enumerable#grep を呼べばいい。ブロックつきで呼ぶと、ブロックを評価した結果の配列になる。
%w(abc def ghi).grep(/^a/) {|i| i.capitalize } # => ['ABC']
こんなかんじで。 Enumerable#map を同時に実行するようなもの、と考えていいとおもう。
で、ブロックではブロックローカルなスコープになるわけで、ここで $~ などが望んだ通りの値を返してくれる。
%w(abc def ghi).grep(/(.).(.)/) { [$2, $1] } # => [['c','a'],['f','d'],['i','g']]
このとおり。