後方参照を行わずにグループ化する(?: )

正規表現のパターンの一部を括弧()を括ると、グループ化される他にあとからその部分にマッチした文字列を取得(後方参照といいます)することができます。ただグループ化だけが必要で後方参照が不要の場合は後方参照を行わない形でグループ化することができます。ここでは Ruby の正規表現で後方参照を行わずにグループ化する方法について解説します。

(2021 年 06 月 30 日公開 / 2022 年 10 月 11 日更新)

後方参照が不要なグループ化

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

/color is (RED|red)/

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

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

(?: )

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

/color is (?:RED|red)/

(?: ) の形式で記述した括弧についてはマッチした文字列を $1 などの変数に代入しません。

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

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

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

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

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

※ 後方参照については「パターンをいくつかに分解しそれぞれがマッチした部分を取得する($1, $2, ..)」を参照されてください。

サンプルコード

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

# encoding: UTF-8

def check(str)
  if /(s_)(.+)(_e)/ =~ str then
    puts("○" + str)
    puts($1)
    puts($2)
    puts($3)
  else
    puts("×" + str)
  end
end

def check2(str)
  if /(s_)(?:.+)(_e)/ =~ str then
    puts("○" + str)
    puts($1)
    puts($2)
    puts($3)
  else
    puts("×" + str)
  end
end

puts("(s_)(.+)(_e) にマッチするかどうか")

check("s_END_LINE_e")

puts("(s_)(?:.+)(_e) にマッチするかどうか")

check2("s_END_LINE_e")

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

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

-- --

Ruby の正規表現で後方参照を行わずにグループ化する方法について解説しました。

( Written by Tatsuo Ikura )

広告
Profile
profile_img

著者 / TATSUO IKURA

初心者~中級者の方を対象としたプログラミング方法や開発環境の構築の解説を行うサイトの運営を行っています。