正規表現:先読み

正規表現の先読みを,忘れないうちにやっておきます.ホントは戻り読みもしたいけれど,Onigurumaという正規表現ライブラリが必要なので,とりあえず今日は先読みだけ.

簡単な例

まずは,簡単な例から.

l = "Jeff and Jeffs dogs are walking"

puts l.sub(/\bJeff(?=s\b)/,"Jeff'")

=>
Jeff and Jeff's dogs are walking

この正規表現の場合,Jeffの後にsがつくJeffにマッチし,subでJeffをJeff'に置換しています.戻り読みが出来るのであれば,

sub(/(?<=\bJeff)(?=s\b)/,"'")

で行けます.日本人の場合,名前をローマ字で書くと,先頭だけ大文字,あとは小文字で,最後にsが付く名前は無いので,

sub(/(?<=[A-Z][a-z]*[aiueo])(?=s)/,"'") # 戻り読みが出来る時
sub(/([A-Z][a-z]*[aiueo])(?=s)/,'\1\'') # 戻り読み無しの時

とすれば,例えばTanakasをTanaka'sに置換できます.

数字にコンマを打つ

良くある例ですが,数字にコンマを打つのに先読みはとても便利.15232165なんて,ぱっと見では分かりません.千五百二十三万二千百六十五です.余計読みにくいです.しかし,15,232,165とすれば,あ,せんごひゃくに(ryだな,と分かりますね.これは,正規表現で簡単に出来ます.

n = "15232165"

puts n.gsub(/(\d)(?=(\d\d\d)+\b)/,'\1,')

=>
15,232,165

これでオッケーです.先読みが使えると,

gsub(/(/<=\d)(?=(\d\d\d)+\b)/,',')

でもオッケー.

class String
  def comma
    self.gsub(/(\d)(?=(\d\d\d)+\b)/,'\1,')
  end
end

a = 1422451
b = 1423

print a.to_s.comma , " * " , b.to_s.comma , " = " , (a*b).to_s.comma
puts

こんなことをすると

1,422,451 * 1,423 = 2,024,147,773

マァ,トテモヨミヤスイ!

何に使えるの?

正直,アポストロフィ打ちとコンマ打ち以外に何に使えるのよ,コレ.まぁきっと,いつか役に立つ日が来るさ.