違いは何ですか 。*?および。*正規表現?


142

正規表現を使用して文字列を2つの部分に分割しようとしています。文字列の形式は次のとおりです。

text to extract<number>

私は使用(.*?)<<(.*?)>てきましたが、どれもうまくいきますが、正規表現を少し読んだ後?、式にが必要な理由を知り始めました。私はこのサイトでそれらを見つけた後にそのようにそれをやっただけなので、私は違いが何であるか正確にわかりません。


回答:


172

これは、貪欲な量指定子と貪欲でない量指定子の違いです。

入力を考えます101000000000100

を使用すると1.*1*貪欲です-最後まで一致し1、一致するまでバックトラックし1010000000001ます。
.*?貪欲ではありません。*は何にも一致しませんが、1一致するまで余分な文字を一致させようとし、最終的には一致し101ます。

:全ての数量は、非欲張りモードを持っている.*?.+?.{2,6}?、とさえ.??

あなたの場合、類似したパターンは<([^>]*)>-大なり記号以外に一致します(厳密に言えば、>中間<と以外の0個以上の文字に一致します>)。

Quantifier Cheat Sheetを参照してください。


>記号以外の最後の1つが好きです。
Doug

1
貪欲?と非貪欲の違いの例を説明したり示したりできます??か?
AdrianHHH 2015年

4
承知しました。文字列の場合"abc"、正規表現は、/\w\w?\w/完全な文字列にマッチします"abc"-ので、?貪欲です。/\w\w??\w/怠惰です-一致するだけ"ab"です。"abc"後で失敗した場合にのみ、バックトラックして一致します。
Kobi

184

貪欲と非貪欲について

デフォルトでの正規表現での繰り返しは貪欲です:彼らはできるだけ多くの担当者と一致しようとし、これが機能せずバックトラックする必要がある場合、パターン全体の一致が一致するまで、一度に1つ少ない担当者と一致しようとします見つかりました。その結果、最終的に試合が行われると、貪欲な繰り返しが可能な限り多くの担当者と一致します。

?この動作を変更する数量詞繰り返しとして非貪欲とも呼ばれ、消極的例えばJavaで)(そして時には「怠け者」)。対照的に、この繰り返しでは、最初にできるだけ少ない担当者とのマッチングを試みます。これが機能せず、バックトラックしなければならない場合、もう一度1つの担当者とのマッチングを開始します。その結果、最終的に試合が行われると、しぶしぶ繰り返しはできるだけ少ない担当者と一致します。

参考文献


例1:AからZへ

これら2つのパターンを比較してみましょう:A.*ZA.*?Z

次の入力があるとします。

eeeAiiZuuuuAoooZeeee

パターンは次の一致をもたらします。

まずは何をするかに焦点を当てましょうA.*Z。それは最初に一致した場合にはA.*多くのとしてマッチする、貪欲され、最初の試行.可能な限りを。

eeeAiiZuuuuAoooZeeee
   \_______________/
    A.* matched, Z can't match

Zが一致しないため、エンジンは逆戻りし、.*一致する数を1つ少なくする必要があります.

eeeAiiZuuuuAoooZeeee
   \______________/
    A.* matched, Z still can't match

これはさらに数回行われ、最終的には次のようになります。

eeeAiiZuuuuAoooZeeee
   \__________/
    A.* matched, Z can now match

これでZ一致できるため、全体的なパターンが一致します。

eeeAiiZuuuuAoooZeeee
   \___________/
    A.*Z matched

対照的に、A.*?Z最初の消極的な繰り返しは.できるだけ少なく一致し、その後.必要に応じてより多くを取ります。これが、入力で2つの一致を見つける理由を説明しています。

以下は、2つのパターンが一致したものを視覚的に表したものです。

eeeAiiZuuuuAoooZeeee
   \__/r   \___/r      r = reluctant
    \____g____/        g = greedy

例:代替

多くのアプリケーションでは、上記の入力の2つの一致が望ましいため.*?、貪欲な代わりに消極的な方法を使用.*して、一致の超過を防ぎます。ただし、この特定のパターンについては、否定された文字クラスを使用するより良い代替手段があります。

このパターンは、上記の入力のパターンA[^Z]*Zと同じ2つの一致も検出しA.*?Zます(ideone.comに表示されます)。[^Z]呼ばれるものである否定文字クラス:それは何も一致しますがZ

2つのパターンの主な違いはパフォーマンスにあります。より厳密に言えば、否定された文字クラスは、特定の入力に対して一方向にしか一致できません。このパターンに貪欲または消極的な修飾子を使用するかどうかは関係ありません。実際、一部のフレーバーでは、より優れた処理を行って、いわゆる所有量指定子を使用できます。これは、まったくバックトラックしません。

参考文献


例2:AからZZへ

この例は説明的なものである必要があります。同じ入力を与えられた場合、貪欲、消極的、および否定された文字クラスパターンがどのように異なって一致するかを示しています。

eeAiiZooAuuZZeeeZZfff

これらは、上記の入力に一致するものです。

以下は、それらが一致したものを視覚的に表したものです。

         ___n
        /   \              n = negated character class
eeAiiZooAuuZZeeeZZfff      r = reluctant
  \_________/r   /         g = greedy
   \____________/g

関連トピック

これらは、関心のあるいくつかのトピックをカバーする、stackoverflowに関する質問と回答へのリンクです。

貪欲な繰り返しは別の欲望を上回ることができます


1
ideone.comではなく、rubular.comと言うつもりでした。他の人へ:この投稿を私のために改訂しないでください。他の例とともに、次の改訂時に自分で行います。コメントにフィードバックや提案などをお寄せください。それらも組み込むことができます。
polygenelubricants 2010年


4
この回答は、「
量指定子

この答えは本当に選ばれた答えになるに値します!。詳しい説明ありがとうございます。
masky007

non-greedyのタグを追加しました。その理由は、質問がそれを必要としただけでなく、より多くのユーザーをこの素晴らしい答えに導くためです。言い換えると、優れた回答を提供し、その回答が質問にないタグを使用している場合、OPはタグが優れていることを認識していなかったため、タグを追加します。
Guy Coder

20

あなたが持っているとしましょう:

<a></a>

<(.*)>と一致するa></a場所<(.*?)>と一致しaます。後者は、の最初の一致後に停止し>ます。.*次の式が続く1つまたは0つの一致をチェックします。

最初の式<(.*)>は、最初の式と一致しても停止しません>。の最後の試合まで続き>ます。


これは上記の説明よりも理解しやすいです。
プロメテウス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.