後方参照が不要なグループ化「(?: )」

広告

正規表現のパターン内を括弧()を使ってグループ化することで、変数「$1」「$2」...にマッチした部分文字列が代入されるのですが、括弧()は後方参照するためだけではなく単なるグループ化の場合だけに使うこともあります。

/color is (RED|red)/

このような場合でも後方参照するために括弧で囲まれた部分は変数「$1」などに格納されるのですが、括弧と変数の関係はパターン内で括弧が表れた順に自動的に決まるため、後から括弧を追加すると対応する変数も全て変わってしまいます。

単にグループ化のためだけに括弧()を使用し、後方参照は行われないようにするには括弧()の代わりに(?: )が用意されています。

(?: )

先ほどの正規表現を書き換えると次のようになります。

/color is (?:RED|red)/

「(」の直後に「?:」が記述されている括弧については部分文字列を変数に代入しません。

具体的な例で考えてみます。

/(s_)(.+)(_e)/ =~ "s_END_LINE_e"

上記の場合、変数「$1」には「s_」にマッチする部分文字列、変数「$2」には「.+」にマッチする部分文字列、変数「$3」には「_e」にマッチする部分文字列が代入されます。では真ん中の括弧()を(?:)に変更します。

/(s_)(?:.+)(_e)/ =~ "s_END_LINE_e"

上記の場合、変数「$1」には「s_」にマッチする部分文字列、変数「$2」には「_e」にマッチする部分文字列が代入されます。「.+」は括弧で囲まれていますが後方参照は行われません。

サンプルプログラム

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

test4-1.rb

#! ruby -Ku
require "kconv"

def check(str)
  if /((¥d+)(yen))/ =~ str then
    print(Kconv.tosjis("○") + str + "¥n")
    print("  [" + $1 + "]¥n")
    print("  [" + $2 + "]¥n")
    print("  [" + $3 + "]¥n")
  else
    print(Kconv.tosjis("×") + str + "¥n")
  end
end

print(Kconv.tosjis("((¥d+)(yen)) にマッチするかどうか¥n¥n"))

check("1980yen")
check("340yen")

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

後方参照が不要なグループ化「(?: )」

( Written by Tatsuo Ikura )