以下2記事で、正規表現による検索と置換を解説しました。
本記事では、上記で解説した内容を Rubyのソースコード上で実装してみます。
上記の2記事で学んだことが理解できていれば、見た目は難しいですが理解できるはずです。
忘れていたとしても、上記2記事を見返せば大丈夫ですよ!
正規表現の基本を確認
文字列を生成する場合、ダブルクウォーテーション「”」で囲いました。正規表現の場合、今度はスラッシュ「/」で囲います。
単純に含まれるかどうかだけ =~
単純にマッチするものがあるかどうかを確認するだけなら、=~で対応できます。
str = "aaaabcc" if /abc/ =~ str puts "マッチします" else puts "マッチしません" end
[実行結果]
マッチします
ちなみに、if文の条件式は何を返しているのでしょうか?trueでしょうか、falseでしょうか?
単純にそこだけ出力してみましょう。
str = "aaaabcc" puts /abc/ =~ str
[実行結果]
3
先頭をゼロとして考えると4、つまりマッチした箇所の開始位置を返しています。
Rubyの世界ではnilとfalseだけが偽なので、先のif文が成立するというわけです。
subを使う
今度はsubを使って置換してみましょう。
str = "aaaabcc" puts str.sub(/abc/,"123")
[実行結果]
aaa123c
簡単ですね。置換できました。
さらにsubが便利なのは、ブロックを受け取ることができます。
先の例で、マッチした部分を大文字にしてみましょう。
str = "aaaabcc" repstr = str.sub(/abc/) do |rep| rep.upcase end puts repstr
[実行結果]
aaaABCc
大文字にできました。
gsubを使う
subはマッチした最初の箇所だけ置換します。それに対してgsubは、マッチした全ての箇所を変換します。
str = "aaaabccabcaaabcacc" puts "subの場合:" + str.sub(/abc/,"123") puts "gsubの場合:" + str.gsub(/abc/,"123")
[実行結果]
subの場合:aaa123cabcaaabcacc gsubの場合:aaa123c123aa123acc
両者を比較すると、違いがよくわかりますね。
オプションを使う
オプションを使って、大文字小文字を区別せず変換してみましょう。
str = "aaaaBccabCaaabcacc" puts "オプションあり:" + str.gsub(/abc/,"123") puts "オプションなし:" + str.gsub(/abc/i,"123")
[実行結果]
オプションあり:aaaaBccabCaa123acc オプションなし:aaa123c123aa123acc
オプションがない場合は大文字小文字が区別されて、最後のabcだけしか置換されませんでした。
一方オプションがある場合は、大文字小文字が区別されず置換されました。
オプションをまとめておきます。
scanを使う
今度はscanを使って、先頭から走査してマッチしたものを全て出してみましょう。
str = "aaaabccabcaaabcacc" str.scan(/a.c/) do |result| puts result end
[実行結果]
abc abc abc acc
aとcの間に1文字が挟まれているものをすべて抽出できました。
結果にもうちょっとひねりを加えて、結果を配列に格納してみましょう。
str = "aaaabccabcaaabcacc" array = [] str.scan(/a.c/) do |result| array.push(result) end p array
[実行結果]
["abc", "abc", "abc", "acc"]
配列に格納することができました。
郵便番号をRubyで!
今までの記事ででてきた郵便番号ネタを、Rubyで実装してみましょう!
データは配列に入ったものを対象としていますが、ファイルから読み込むなどなど応用を利かしてみてください。
郵便番号でないものをあぶりだす!
array = [ "123-4567", "098-7654", "1234567", "a123456", "1234-567" ] array.each do |str| if /^(?!\d{3}-\d{4}).*$/ =~ str puts str end end
実行結果
1234567 a123456 1234-567
郵便番号のハイフンを消す
array = [ "123-4567", "098-7654", "1234567", "a123456", "1234-567" ] array.each do |str| /^(\d{3})-(\d{4}).*$/ =~ str puts $1 + $2 if $1 != nil && $2 != nil end
実行結果
1234567 0987654
Ruby特有!名前付きキャプチャ
上記の例では、1つめのカッコが$1で2つめのカッコが$2で、という決め事がありました。
しかしRubyでは、名前付きキャプチャというものがあります。HTMLのタグのようなもので名前をつけることができます。
array = [ "123-4567", "098-7654", "1234567", "a123456", "1234-567" ] array.each do |str| /^(?<first>\d{3})-(?<last>\d{4}).*$/ =~ str puts first + last if first != nil && last != nil end
順番を追うことなく判別できるので、プログラム修正で仕様が変わって、カッコが増減しても大丈夫です。
まとめ
今まで解説してきた手法を、Rubyで実装しました。
前2記事と本解説を合わせて、Rubyで正規表現を扱えるようにがんばってくださいね!