什么是“懒惰”(不情愿)匹配?
与正则表达式匹配时,指针为greedy默认情况下:
Left | Right
\d+ 12345
^ ^
\d+ 12345
^ ^^^^^ Matched!
Lazy与贪婪相反:
Left | Right
\d+? 12345
^ ^
\d+? 12345
^^ ^
12345
^
12345
^
12345
^ Matched!
为什么这有关系?
在匹配中,量词*
+
?
are greedy默认情况下。这可能会导致不必要的行为,特别是当我们想要某些角色时仅在需要完成匹配时才进行匹配,否则省略。
一个典型的例子是当我们想要匹配单个 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>"!
什么可以量化为懒惰?
您可以添加?
在量词和范围后面构造:
+
(one or more), *
(zero or more), ?
(optional);
{n,m}
(between n and m where n < m), {n,}
(n or more), {n}
(exactly n times).
(n and m in the examples are real numbers and satisfies 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"!
正如所演示的,它们匹配得尽可能少。
-
不情愿的量词者会放弃去取悦其他量词者。
(演示目的;如果有人问,我就这么做了not告诉你这样使用 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}
and X{n}?
,几乎没有差异;大多数引擎都会在内部优化掉不情愿的标志。这是因为惰性构造仅适用于动态匹配,其中引擎可以针对量词(需要或贪婪)以一种或另一种方式表现,但不适用于这种情况。
查看regex101,一个完善的正则表达式引擎,带有解释和调试器日志来向您显示指针步骤。
另请阅读Stack Overflow 正则表达式参考!