欲張りなマッチと控え目なマッチ(量指定子?)

広告

繰り返しを意味するメタ文字である「+」、「*」、「?」、「{min,max}」、「{num}」はなるべく長い文字列にマッチしようとします。

/a.+b/

上記の場合「a」で始まり任意の文字(改行除く)が1回以上続き「b」で終わる文字列にマッチします。これを「00a11b22b33b44」に対してマッチさせてみるとマッチする部分としては次の3つの候補があります。

00a11b22b33b44
00a11b22b33b44
00a11b22b33b44

マッチしたかどうかを考えるだけならば気にしなくても構いませんが、文字列の中のどの部分にマッチしたのかが必要になる時には、どの位置にマッチしたかを考えることは重要です。

このような時、繰り返しを表すメタ文字は一番長い文字列にマッチしようとします。つまりマッチする部分は次の箇所となります。

00a11b22b33b44

なお正規表現オブジェクトに対して「=~」メソッドがマッチした場合、マッチした部分が変数「$&」に格納されます。その為、マッチに成功した後で変数「$&」を参照すると対象の文字列の中のどの部分にマッチしたかを確認できます。

サンプルプログラム

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

test8-1.rb

#! ruby -Ku
require "kconv"

def check(str)
  if /a.+b/ =~ str then
    print(Kconv.tosjis("○") + str + "(" + $& + ")" + "¥n")
  else
    print(Kconv.tosjis("×") + str + "¥n")
  end
end

print(Kconv.tosjis("「a.+b」にマッチするかどうか¥n¥n"))

check("00a11b22b33b44")

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

欲張りなマッチと控え目なマッチ(量指定子?)

今回はマッチに成功した場合、マッチした部分も合わせて表示するようにしています。マッチ可能な最大の部分にマッチしていることが確認できます。

控え目なマッチ(最小量指定子)

デフォルトではマッチする範囲が最大になるようにマッチしますが、逆に最小になるようにマッチさせることも可能です。各メタ文字の後に「?」を付けて使用することで最小の部分にマッチするようになります。

+?
*?
??
{min,max}?
{min,}?
{num}?

例として先ほどと同じように任意の文字を表すメタ文字「.」に対して1回以上繰り返しすメタ文字「+?」を使った場合で考えてみます。今回は最小量指定子付きとなっています。

/a.+?b/

上記の場合「a」で始まり任意の文字(改行除く)が1回以上続き「b」で終わる文字列にマッチします。これを「00a11b22b33b44」に対してマッチさせてみるとマッチする部分としては次の3つの候補があります。

00a11b22b33b44
00a11b22b33b44
00a11b22b33b44

今回は最小量指定子の「?」が付けられていますので、最も短い文字列にマッチしようとします。つまりマッチする部分は次の箇所となります。

00a11b22b33b44

サンプルプログラム

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

test8-2.rb

#! ruby -Ku
require "kconv"

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

print(Kconv.tosjis("「a.+?b」にマッチするかどうか¥n¥n"))

check("00a11b22b33b44")

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

欲張りなマッチと控え目なマッチ(量指定子?)

マッチ可能な候補の中で最小の部分にマッチしていることが確認できます。

( Written by Tatsuo Ikura )

関連記事 (一部広告含む)