プログラミング/ruby/正規表現 のバックアップ(No.1)

更新


公開メモ

近年導入された新しい機能を中心に、いろいろ試した結果をメモします

http://docs.ruby-lang.org/ja/1.9.3/doc/spec=2fregexp.html

ここを見ながら。

名前付きキャプチャ

名前を付けておいて、後で参照できる。

LANG:irb
irb> "aabaac" =~ /
irb/          (?<cap1>..)   # 'aa' にマッチ
irb/          .             # 'b' にマッチ
irb/          \k<cap1>      # cap1 と名付けた括弧でキャプチャした 'aa' にマッチ
irb/          /x
=> 0
irb> Regexp.last_match.names
=> ["cap1"]
irb> Regexp.last_match['cap1']
=> ["cap1"]

Regexp.last_match では名前付きキャプチャを通常通り数値で参照することも可能

LANG:irb
irb> "aabaac" =~ /
irb/          (?<cap1>..)   # 'aa' にマッチ
irb/          .             # 'b' にマッチ
irb/          \k<cap1>      # cap1 と名付けた括弧でキャプチャした 'aa' にマッチ
irb/          /x
=> 0
irb> Regexp.last_match.length
=> 2
irb> Regexp.last_match[0]
=> "aabaa"
irb> Regexp.last_match[1]
=> "aa"
irb> $0
=> "irb"
irb> $&
=> "aabaa"
irb> $1
=> "aa"

正規表現中では名前付きキャプチャを数値で後方参照することはできない

LANG:irb
irb> "aba" =~ /
irb/          (?<cap1>.)    # 'a' にマッチ
irb/          .             # 'b' にマッチ
irb/          \1            # 1番目の括弧でキャプチャした 'a' にマッチ?  → できない!
irb/          /x
=> 0
SyntaxError: (irb):5: numbered backref/call is not allowed. (use name): /
         (?<cap1>..)   # 'aa' にマッチ
         .             # 'b' にマッチ
         \1            # 'aa' にマッチ???
         /x
        from /usr/bin/irb:12:in `<main>'
irb> "aabaac" =~ /
irb/          (..)          # 'aa' にマッチ
irb/          .             # 'b' にマッチ
irb/          \1            # 1番目の括弧でキャプチャした 'aa' にマッチ → 名前が付いていなければOK
irb/          /x
=> 0

MatchData へのインデックスは Symbol でも良い

名前付きキャプチャを使うと複雑な文字列を分かりやすく要素に分解できます。

LANG:irb
irb> result = "Osamu Takeuchi <osamu@big.jp>".match /^(?<name>.+)\s<(?<email>[^@]+@[^@]+)>$/
=> #<MatchData "Osamu Takeuchi <osamu@big.jp>" name:"Osamu Takeuchi" email:"osamu@big.jp">
irb> result[:name]
=> "Osamu Takeuchi"
irb> result[:email]
=> "osamu@big.jp"

複雑な文字列を要素に分解 (通常版)

LANG:irb
irb> "Osamu Takeuchi <osamu@big.jp>" =~ /^(.+)\s<([^@]+@[^@]+)>$/
=> 0
irb> $1
=> "Osamu Takeuchi"
irb> $2
=> "osamu@big.jp"

数値の方がシンプル???

相対的な後方参照

上記の例を、相対位置を使って書けば以下のようになります。

LANG:irb
irb> "aabaac" =~ /
irb/          (..)          # 'aa' にマッチ
irb/          .             # 'b' にマッチ
irb/          \k<-1>        # 直前の括弧でキャプチャした 'aa' にマッチ
irb/          /x
=> 0

正規表現を結合するときに便利

相対位置で指定しておくことにより、結合した正規表現の中でもキャプチャと後方参照との対応関係が崩れなくなります。

LANG:irb
irb> regexp = /(..).\k<-1>/
=> /(..).\k<-1>/
irb> /#{regexp}#{regexp}/.inspect
=> "/(?-mix:(..).\\k<-1>)(?-mix:(..).\\k<-1>)/"

MatchData へも負のインデックスを与えられる

LANG:irb
irb> "Osamu Takeuchi <osamu@big.jp>" =~ /^(.+)\s<([^@]+@[^@]+)>$/
=> 0
irb> Regexp.last_match[-1]
=> "osamu@big.jp"
irb> Regexp.last_match[-2]
=> "Osamu Takeuchi"

質問・コメント


Counter: 7090 (from 2010/06/03), today: 3, yesterday: 0