先読みを使ったパターンを作成する

正規表現では先読みを使ったパターンを定義することができます。ここでは Ruby の正規表現で先読みを使ったパターンを使用する方法について解説します。

(Last modified: )

先読みを使ったパターン

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

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

分かりにくい概念なので具体的な例を元に確認していきます。次のようなパターンを作成します。

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

このパターンは「a」で始まり、任意の文字が 3 文字続き、最後に「b」で終わる文字列にマッチします。例えば次のような文字列とマッチします。

○ a012b
○ aboub
× awoomgb
× ab

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

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

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

× ab
× abc
○ abcd
○ abcde
× acdb

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

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

/Color(?=.Red|Blue)/

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

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

/(?=.Red|Blue)Color/

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

サンプルコード

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

# encoding: UTF-8

def check1(str)
  if /Red(?=Color)/ =~ str then
    puts("○" + str + "(" + $& + ")")
  else
    puts("×" + str)
  end
end

def check2(str)
  if /Red(Color)/ =~ str then
    puts("○" + str + "(" + $& + ")")
  else
    puts("×" + str)
  end
end

def check3(str)
  if /(?=Red)Color/ =~ str then
    puts("○" + str + "(" + $& + ")")
  else
    puts("×" + str)
  end
end

puts("/Red(?=Color)/ にマッチするかどうか")
check1("RedColor")
puts()

puts("/Red(Color)/ にマッチするかどうか")
check2("RedColor")
puts

puts("/(?=Red)Color/ にマッチするかどうか")
check3("RedColor")

下記のように実行して下さい。

先読み

-- --

Ruby の正規表現で先読みを使ったパターンを使用する方法について解説しました。

( Written by Tatsuo Ikura )

Profile
profile_img

著者 / TATSUO IKURA

プログラミングや開発環境構築の解説サイトを運営しています。