Ruby 3.2 - MatchData

Ruby 3.2 アドベントカレンダーの13日目の記事です。

qiita.com


MatchData

MatchData#byteoffset

Feature #13110: Byte-based operations for String - Ruby master - Ruby Issue Tracking System

MatchData は正規表現に適合した文字列を表すクラス。 MatchData#offset で適合した全体や括弧の部分の範囲を文字単位で取得できる。

s = "あいう123えおabcかきく"
m = s.match(/(\w+)\W*(\w+)/)  #=> #<MatchData "123えおabc" 1:"123" 2:"abc">
m.offset(0)  #=> [3, 11]   正規表現全体に適合したのは s[3...11]
m.offset(1)  #=> [3, 6]    最初の括弧に適合した '123' は s[3...6]
m.offset(2)  #=> [8, 11]   次の括弧に適合した 'abc' は s[8...11]

Ruby 3.2 でこれをバイト単位で取り出せるようにした MatchData#byteoffset が追加された。

m.byteoffset(0)  #=> [9, 21]    正規表現全体に適合したのは s.b[9...21]
m.byteoffset(1)  #=> [9, 12]    最初の括弧に適合した '123' は s.b[9...12]
m.byteoffset(2)  #=> [18, 21]   次の括弧に適合した 'abc' は s.b[18...21]

MatchData#deconstruct / MatchData#deconstruct_keys

Feature #18821: Expose Pattern Matching interfaces in core classes - Ruby master - Ruby Issue Tracking System

Ruby 3.2 で MatchData#deconstructMatchData#deconstruct_keys が追加された。

MatchData#deconstructMatchData#captures のエイリアス。

s = "あいう123えおabcかきく"
m = s.match(/(\w+)\W*(\w+)/)  #=> #<MatchData "123えおabc" 1:"123" 2:"abc">
m.deconstruct  #=> ["123", "abc"]

正規表現内の括弧には名前をつけることができて MatchData#[]MatchData#named_captures で参照できる。

m = s.match(/(?<a>\w+)\W*(?<b>\w+)/)  #=> #<MatchData "123えおabc" a:"123" b:"abc">
m['a']  #=> "123"
m['b']  #=> "abc"
m.named_captures  #=> {"a"=>"123", "b"=>"abc"}

MatchData#deconstruct_keys はシンボルで名前を指定して参照できる。nil を指定するとすべての名前付き括弧が参照できる。

m.deconstruct_keys(nil)   #=> {:a=>"123", :b=>"abc"}
m.deconstruct_keys([:b])  #=> {:b=>"abc"}

deconstructdeconstruct_keys という名前でピンときた人もいると思うけど、これによって MatchData をパターンマッチで使えるようになるということらしい。

IP_REGEX = /
  (?<first_octet>\d{1,3})\.
  (?<second_octet>\d{1,3})\.
  (?<third_octet>\d{1,3})\.
  (?<fourth_octet>\d{1,3})
/x

'192.168.1.1'.match(IP_REGEX) in {first_octet: '192', fourth_octet: '1'}  #=> true

自分はピンとこなかった。パターンマッチよくわからん。