2014年7月17日木曜日

正規表現における量指定子(greedy,reluctant,possessive)とはなにか

Javaの正規表現では、quantifier(量指定子)の種類としてGreedy、Reluctant、Possessiveというものがある。

webを検索すると説明はいろいろ出てくるが、日本語の付け方が違ったり、3つを並べて比較してなかったりしてわかりづらかったので、これの違いを整理してみる。

まずquantifier(量指定子)とはなにか。

これは"量"指定子という名称の通り、一致させたい文字の数を指定するための表現方法。

例えば、テキストファイルを検索するためによく使われる下記の表現。

.*\.txt

これは任意の文字が0個以上続いたあとに、".txt"が続く文字列を表現したものであり、*がquantifier(量指定子)に当たる。

Greedy Quantifier

greedy(欲張り)と名前が付いている通り、この量指定子を使うとなるべく多くの繰り返し数になるようにマッチする。

たとえば下記の例がGreedy Quantifier。

.*foo
このとき、xfooxxxxxxfooという文字列にマッチさせようとすると、次の文字列がマッチする。

xfooxxxxxxfoo

Reluctant Quantifier

 reluctant(気乗りしない)と名前がついており、この量指定子を使うとなるべく少なくなる繰り返し数になるようににマッチする。

下記の例がReluctant Quantifier

.*?foo
このとき、先ほどと同様にxfooxxxxxxfooという文字列にマッチさせようとすると、次の文字列がマッチする

xfoo

 Possessive Quantifier

 possesiveは「所有の」という意味がある。この量指定子を使うとGreedyと同様になるべく多くの繰り返し数になるようにマッチする。Greedyとの違いは、正規表現全体のマッチよりも、Possessive Quantifierを使った部分のマッチが優先される、ということ。

例えば下記の例がpossessive quantifier。

.*+foo
同様にxfooxxxxxxfooにマッチさせようとすると、結果は何にもマッチしない。
なぜなら、".*+"がなるべく多くの繰り返し数になるようにマッチするため、この部分だけでxfooxxxxxxfoo文字列全体がマッチする。そのため、fooの部分が一致する場所がなくなり、全体としてはマッチしない、という結果になる。


ここで、それぞれのQuantifierとfooの部分がマッチした箇所を整理すると次のようになる。

Greedy

Quantifierがヒットした場所  xfooxxxxxx
fooがヒットした場所 foo

Reluctant

Quantifierがヒットした場所  xfoo
fooがヒットした場所 xxxxxxfoo

Possessive

Quantifierがヒットした場所  xfooxxxxxxfoo
fooがヒットした場所 なし


参考文献




0 件のコメント:

コメントを投稿