LoginSignup
8
5

More than 5 years have passed since last update.

絶対最大量指定子(possessive quantifier)について

Last updated at Posted at 2018-02-28

Rubyの公式サイトを見ていた際に、
絶対最大量指定子(possessive quantifier)について文章だけでは分からなかったのでまとめます。

説明の為、最大量指定子・最小量指定子についても記載します。

最大量指定子(greedy quantifier)

直前の部分式を何回繰り返すかを指定します。このような繰り返しを 表すメタ文字列を量指定子(quantifier)と呼びます。

* 0回以上
+ 1回以上
? 0回もしくは1回
{n} ちょうどn回(nは数字)
{n,} n回以上(nは数字)
{,m} m回以下(mは数字)
{n,m} n回以上m回以下(n,mは数字)

これらは「欲張り(greedy)」にマッチします。 マッチが成功する、最長の文字列にマッチしようとします。 そのため、これらの量指定子は特に最大量指定子(greedy quantifier) と呼ばれます。

※引用:Ruby 2.5.0 リファレンスマニュアル > 正規表現

最小量指定子(reluctant quantifier)

一方、以下のメタ文字列(普通の繰り返しメタ文字列に ? を付加したもの) はマッチが成功する、最短の文字列にマッチします。そのため、これらの 量指定子は特に最小量指定子(reluctant quantifier)と呼ばれます。

*? 0回以上
+? 1回以上
?? 0回もしくは1回
{n,}? n回以上(nは数字)
{,m}? m回以下(mは数字)
{n,m}? n回以上m回以下(n,mは数字)

※引用:Ruby 2.5.0 リファレンスマニュアル > 正規表現

絶対最大量指定子(possessive quantifier)

強欲な数量子とも呼ぶそうです。

以下のメタ文字列は、最大量指定子のように最長のマッチをしますが、 一度マッチすると、その後マッチに失敗してもバックトラックしません。 つまりマッチ済みの文字列を手放さずにマッチに失敗します。 これらの量指定子は絶対最大量指定子と呼ばれます。

*+ 0回以上
++ 1回以上
?+ 0回もしくは1回

※引用:Ruby 2.5.0 リファレンスマニュアル > 正規表現

絶対最大量指定子の説明で分からなかった箇所

一度マッチすると、その後マッチに失敗してもバックトラックしません。 つまりマッチ済みの文字列を手放さずにマッチに失敗します。

まず、バックトラックとはなんぞや?ということでググりました。
調べたところバックトラック自体は正規表現固有の用語ではないんですね。
Wikipedia > バックトラッキング

正規表現のバックトラックについては、以下のブログの内容が分かりやすかったです。
Shin x Blog > パフォーマンスを意識して正規表現を書く

検証

上記を踏まえてRubyの正規表現を試してみました。

最大量指定子

最大量指定子
 /^\d+\d/.match('123')
=> #<MatchData "123">

^\d+ が 123 にマッチ成功。その後 \d がマッチに失敗、バックトラックします。
^\d+ が 12 にマッチ成功。その後 \d が 3 にマッチ成功。
マッチ結果は "123" となります。

絶対最大量指定子

絶対最大量指定子
 /^\d++\d/.match('123')
=> nil

^\d++ が 123 にマッチ。その後 \d がマッチに失敗、バックトラックしません。
マッチ結果は nil となります。

あとがき

絶対最大量指定子については今のところ使う場面が思い付かないですが、正規表現のパフォーマンスを気にする場面で使うものなのでしょうか?
いずれ正規表現についてもっと詳しく調べてみたいなーと思いました。

8
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5