blog.waterlow.work

Ruby, Rails, js, etc...

【Ruby】Gold試験対策-組み込み変数/定数、正規表現、MatchDataについて不満

Rury技術者認定では組み込み変数や定数を問うような問題も数問出されます。公式資格教科書はあんまり親切な書き方はしてなかったし、パーフェクトRubyにも詳しく書いてなかったのでRubyでは非推奨なのでしょうか?

組み込み変数とは?

グローバル変数であらかじめ定義されていてそれぞれの動作に応じて値が格納される。
今回は主に特殊変数を見るが、Perl由来らしい。

result = /(\d{3,4})-?(\d{3,4})-?(\d{3,4})-?/.match("bf123-456-7890aft")
p result.equal?($~) #=> true
p $& #=> "123-456-7890-" 
p $~ #=> #<MatchData "123-456-7890" 1:"123" 2:"456" 3:"7890">
p $~[1] == $1 #=> true
p $0 #=> "003var.rb"
p $` #=> "bf"
p $' #=> "aft"
p $+ #=> "7890"
/((\d{3,4})-?){3}/.match("123-456-7890-")
p result.equal?($~) #=> false
p $~ #=> #<MatchData "123-456-7890-" 1:"7890-" 2:"7890">

正規表現のマッチングに応じて値が格納されるものたち。直近のマッチングの結果が$~に格納される。データ型はRagexp#match同様MatchDataで返される。MatchData型は配列チックにresult[1]でアクセスできるため$~[1]も同様だが、組み込み変数として$1、$2…というものも用意されている。ただ$0はファイル名が格納される特殊変数のため注意。

問題なのは2つ目のマッチングなのですが、動作が微妙。3〜4桁の数字の組*3だから繰り返しでまとめられるかなと思ったのですが、全体のマッチの結果はOKだけど、括弧でグルーピングしたところの結果が理想とは異なってました。
(実際に書かれている括弧にしか反応しない様子。)
もし電話番号やクレジット番号から部分的に抽出する場合は、1回目のマッチングのような書き方でないとダメのようですね。それかオーバーライドするか。でも、電話やカードの番号は高々20桁ぐらいなのでベタ書きでも差支えないかもしれませんね。

長くなりました。

def test_method
  begin
    raise
  rescue
    p $! #=> RuntimeError
    p $@ #=> ["004error.rb:3:in `test_method'", "004error.rb:11:in `<main>'"]
    p $@[0].class #=> String 
    p $*.equal?(ARGV) #=> true
  end
end
test_method

$!は直近のエラー、$@はそのバックトレースを格納します。あと$*はコマンドライン引数。
この辺は、知らない人にはぱっと見何かわからないですね。