StupidDog's blog

IT関連の手近な所で、疑問に思った事を調べた記録

「string#matchが返すのは配列じゃなかったよ」|ただいまRubyの修行中です

はじめに

ちょこちょこと、String#match正規表現とグループを使って文字列の切り出しをしていたのです。
でも、$1とか$2だと処理しずらいな~と思い、ちらっとサンプルコードを見たところ

s = "<hello> <world>"
if md = s.match(/<(\w+)>/)
  puts md[0]
  puts md[1]
end

「$1とか$2じゃなくて配列を返すのか~」と安易に判断してArray#mapを繋げてみたところ…

puts "123,456,789,987".match(/(\d+),(\d+)/).map(&:to_i)

mapメソッドなんて無いと怒られましたっ

code.rb:3:in `<main>': undefined method `map' for #<MatchData "123,456" 1:"123" 2:"456"> (NoMethodError)

メッセージを見るとMatchDataクラスのオブジェクトが返って来てる。

MatchDataクラスとは?

Ruby 2.1.0 リファレンスマニュアル class MatchData
正規表現のマッチに関する情報を扱うためのクラスで、配列のように[]でも値が取得できるように定義されています。
折角なので、面白そうなメソッドが無いかリファレンスを眺めて、どんなメソッドがあるのか個人用に一覧化してみたり。

メソッド 戻り値 説明
マッチした文字列とその前後の取得
to_s  String マッチした文字列全体を返す
pre_match  String マッチした部分より前の文字列を返す($`と同じ)
post_match  String マッチした部分より後ろの文字列を返す($'と同じ)
グループにマッチした文字列の取得
captures  [String] $1, $2,...を格納した配列を返す。
to_a  [String] $&, $1, $2,...を格納した配列を返す。
values_at(*index) [String] 正規表現中のn番目の括弧にマッチした部分文字列の配列を返す(0番目は$&)
マッチした文字列の位置取得
begin(n) Fixnum n番目の部分文字列先頭のオフセット。マッチしていなければnil
end(n) Fixnum n番目の部分文字列終端のオフセット。マッチしていなければnil
offset(n) [Fixnum] n番目の部分文字列のオフセットの配列[start,end]を返す。
比較結果の情報取得
regexp Regexp 自身の元になった正規表現オブジェクトを返す
string  String マッチ対象になった文字列の複製を返す
names [Array] 名前付きキャプチャの名前を文字列配列で返す(=self.regexp.names)
length/size Fixnum 部分文字列の数を返す(=self.to_a.size,$&も含も含まれると言うこと)

values_at(*index)メソッドなんかは面白いかも。

irb(main):001:0> "2014,1,24".match(/(\d+),(\d+),(\d+)/).values_at(2,3,1).join("/")
=> "1/24/2014"