?
ここのマークが「怠け者」を意味することは理解しています。
私の質問は本質的に[0-9]{2}?
vsです[0-9]{2}
それらは同じですか?
もしそうなら、なぜ前者の式を書いているのでしょうか? レイジー モードはよりコストのかかるパフォーマンスではありませんか?
そうでない場合、違いを教えていただけますか?
?
ここのマークが「怠け者」を意味することは理解しています。
私の質問は本質的に[0-9]{2}?
vsです[0-9]{2}
それらは同じですか?
もしそうなら、なぜ前者の式を書いているのでしょうか? レイジー モードはよりコストのかかるパフォーマンスではありませんか?
そうでない場合、違いを教えていただけますか?
正規表現と一致する場合、ポインターはデフォルトで貪欲です。
Left | Right
\d+ 12345
^ ^
\d+ 12345
^ ^^^^^ Matched!
怠惰は貪欲の反対です。
Left | Right
\d+? 12345
^ ^
\d+? 12345
^^ ^
12345
^
12345
^
12345
^ Matched!
一致では、量指定子*
+
?
はデフォルトで貪欲です。これは望ましくない動作につながる可能性があります。特に、一致が完了するために必要な場合にのみ特定の文字を一致させ、それ以外の場合は省略したい場合です。
典型的な例は、単一の XML タグに一致させたい場合です。これは で失敗し<.*>
ます。
Left | Right
<.*> <p>hi</p><br /><p>bye</p>
^ ^
<.*> <p>hi</p><br /><p>bye</p>
^^ ^^^^^^^^^^^^^^^^^^^^^^^^
<.*> <p>hi</p><br /><p>bye</p>
^ < [backtrack!]
<.*> <p>hi</p><br /><p>bye</p>
^ ^ Matched "<p>hi</p><br /><p>bye</p>"!
Left* | Right
<.*?> <p>hi</p><br /><p>bye</p>
^ ^
<.*?> <p>hi</p><br /><p>bye</p>
^^^ ^ [can we stop? we're lazy [yes]]
<.*?> <p>hi</p><br /><p>bye</p>
^ ^ Matched "<p>"!
?
数量詞と範囲の後ろに構文を追加できます。
+
(1 つ以上)、*
(ゼロ以上)、?
(オプション);
{n,m}
(n と m の間、n < m)、{n,}
(n 以上)、{n}
(正確に n 回)。
(例中の n と m は実数で、n, m ϵ Nを満たす)
気が進まない量指定子は、先に進みたがりません。エンジンは、残りの部分が成功するために絶対に必要な場合に
のみ一致を試行するという考慮の下で、可能な限り多くまたはできるだけ少なく一致することが許可されます。次のケースを参照してください。
Left | Right
abc* abccccd
^ ^
abc* abccccd
^ ^
abc* abccccd
^ ^
abc* abccccd
^^ ^^^^ Matched "abcccc"!
Left* | Right
abc*? abccccd
^ ^
abc*? abccccd
^ ^
abc*? abccccd
^^^ ^ [must we do this? we're lazy [no]]
Matched "ab"!
示されているように、それらは可能な限り一致しません。
気が進まない量指定子は、他の量指定子を楽しませることをあきらめます。
(デモンストレーション目的; 誰かが尋ねたとしても、このように RegExp を使用しても問題ないとは言いませんでした。)
Left | Right
c+c+ abccccd
^ ^
c+c+ abccccd
^^ ^^^^
c+c+ abccccd
^ < [backtrack]
c+c+ abccccd
^^ ^ Matched "cccc"!
(c+ -> @ccc; c+ -> @c)
Left* | Right
c+?c+ abccccd
^ ^
c+?c+ abccccd
^^^ ^ [pass]
c+?c+ abccccd
^^ ^^^ Matched "cccc"!
(c+? -> @c; c+ -> @c)
X{n}
X{n}?
よくできた正規表現エンジンであるregex101を確認してください。このエンジンには、説明とポインターの手順を示すデバッガー ログが付属しています。スタック オーバーフロー正規表現リファレンスもお読みください。
と の間に違いはありません。[0-9]{2}
[0-9]{2}?
貪欲なマッチングと怠惰なマッチング ( a の追加) の違い?
は、バックトラッキングに関係しています。正規表現エンジンは、テキスト (左から右)に一致するように構築されています。したがって、ある範囲の文字に一致する式を要求すると、可能な限り多くの文字に一致するのは論理的です。
string があるとしますacac123
。
[a-z]+c
(+
は 1 回以上の繰り返しまたは)の貪欲な一致を使用する場合{1,}
:
[a-z]+
で一致acac
し、失敗します1
c
が、 で失敗します1
aca
してc
これを遅延 ( [a-z]+?c
) にすると、異なる応答 (この場合) が得られ、より効率的になります。
[a-z]+?
と一致a
しますが、次の文字が式の残りの部分と一致するため停止しますc
c
一致し、正常に一致a
し、c
(バックトラッキングなしで)これで、 と の間に違いがないことがわかります。 は範囲ではなく、貪欲な一致でもバックトラッキングが発生しないためです。遅延一致は(0+ 繰り返しまたは) またはでよく使用されますが、範囲で使用することもできます(はオプションです)。X{#}
X{#}?
{#}
*
{0,}
+
{m,n}
n
これは、可能な限り少ない文字数で一致させたい場合に不可欠であり、(文字列の).*?
スペースを埋めたい場合に式でよく見かけます。ただし、多くの場合、遅延一致は悪い/非効率的な正規表現の例です。多くの人は、二重引用符で囲まれたすべてのものに一致するようなことをします.foo.*?bar
foo bar filler text bar
foo:"(.*?)"
foo:"([^"]+)"
"
最後のメモは、?
通常、「オプション」または試合{0,1}
時間を意味します。範囲 ( 、、、または別の)?
で使用する場合にのみ、一致を遅延させます。これは、怠け者にならないことを意味します(すでに言ったように無意味です) が、代わりにオプションになります。ただし、レイジーな「オプションの」マッチを行うことができます: レイジーに0-1 回マッチします。{m,n}
*
+
?
X?
X
{#}?
[0-9]??