先読みを使ったパターン

広告

先読みをパターン内で使用する場合、先読みを行うパターンを「(?=」から「)」の間に記述します。

/パターン(?=先読みパターン)パターン/

分かりにくい概念なので具体的な例を元に確認していきます。

/(a)(...)(b)/

例として上記のような正規表現オブジェクトを作成します。この正規表現は「a」で始まり、任意の文字が3文字続き、最後に「b」で終わる文字列にマッチします。

○ a012b
○ aboub
× awoomgb
× ab

今度は真ん中のパターンが先読みとなっています。

/(a)(?=...)(b)/

今度の正規表現は「a」で始まり、「a」の後に任意の文字が3文字続くかどうかだけを確認し、マッチしていれば改めて「a」の後に「b」が続く文字列にマッチします。結果的に「a」の後に「b」で始まり任意の文字が2文字続く文字列にマッチします。

× a012b
○ aboub
× awoomgb
× ab

このように先読みとして指定したパターンは、パターンにマッチするかどうかは確認しますがマッチした文字列を取得しません。先読みのパターンがマッチすれば、先読みの部分が無かったようにその後のパターンがマッチするかどうかを確認します。

どのような場合に使えるのかが良く分かりませんが、例えば次の例で考えてみます。

/Color(?=.Red|Blue)/

上記の場合、「ColorRed」又は「ColorBlue」が含まれる文字列にマッチしますが、マッチした部分文字列としては「Color」だけです。「Red」や「Blue」は「Color」の後に続いて記述されているかどうかを確認は行われますが確認するだけです。

もう1つ例を見てみます。

/(?=.Red|Blue)Color/

上記は「RedColor」や「BlueColor」にマッチするわけではありません。まず「Red」又は「Blue」にマッチするかどうかを確認し、マッチした場合はマッチした文字列の先頭から改めて「Color」とマッチするかどうかを調べます。よってこのパターンは絶対にマッチしません。先読みの後にさらにパターンがある場合は、先読みとその後のパターンが同時にマッチする文字列にだけマッチします。

サンプルプログラム

では簡単なプログラムで確認して見ます。

test1-1.rb

#! ruby -Ku
require "kconv"

def check1(str)
  if /Red(?=Color)/ =~ str then
    print(Kconv.tosjis("○") + str + "(" + $& + ")¥n")
  else
    print(Kconv.tosjis("×") + str + "¥n")
  end
end

def check2(str)
  if /Red(Color)/ =~ str then
    print(Kconv.tosjis("○") + str + "(" + $& + ")¥n")
  else
    print(Kconv.tosjis("×") + str + "¥n")
  end
end

def check3(str)
  if /(?=Red)Color/ =~ str then
    print(Kconv.tosjis("○") + str + "(" + $& + ")¥n")
  else
    print(Kconv.tosjis("×") + str + "¥n")
  end
end

print(Kconv.tosjis("/Red(?=Color)/ にマッチするかどうか¥n"))
check1("RedColor")
print("¥n")

print(Kconv.tosjis("/Red(Color)/ にマッチするかどうか¥n"))
check2("RedColor")
print("¥n")

print(Kconv.tosjis("/(?=Red)Color/ にマッチするかどうか¥n"))
check3("RedColor")

上記のプログラムを「test1-1.rb」として保存します。文字コードはUTF-8です。そして下記のように実行して下さい。

先読み

( Written by Tatsuo Ikura )