我主要关心的是Java风格,但我也很欣赏有关其他人的信息。
假设你有一个这样的子模式:
(.*)(.*)
不是很有用,但是假设这两个捕获组(比如,\1
和\2
)是更大模式的一部分,与这些组的反向引用相匹配等。
所以两者都是贪婪的,因为他们试图尽可能地捕捉,只在必要时少花钱。
我的问题是:谁更贪婪? \1
是否具有优先权,只有在必须时才提供\2
的份额?
怎么样:
(.*)(.*)(.*)
我们假设\1
确实优先。让我们说它过于贪婪,然后吐出一个角色。谁先得到它?它总是\2
还是\3
?
我们假设\2
得到\1
的拒绝。如果这仍然不起作用,谁现在吐出来? \2
向[{1}}吐出,或\3
先向\1
吐出另一个吗?
如果你写这样的话会怎么样:
\2
现在(.*)(.*?)(.*)
不愿意。这是否意味着\2
吐出\1
,而\3
只是不情愿地接受\2
的拒绝?
对我来说,如果不提供具体的例子来展示我如何使用这些模式,也许这是错误的,但这里有一些:
\3
答案 0 :(得分:15)
\1
将具有优先权,\2
和\3
将始终不匹配。然后\2
优先于\3
。
作为一般规则这样想,反向跟踪将仅出现以满足匹配,它不会发生以满足贪婪,所以左边最好:)
回答跟踪和贪婪是我在这里要解决的问题,我建议friedl's Mastering Regular Expressions
答案 1 :(得分:8)
添加具体示例可以彻底改变问题的本质。它仍然像我在第一个答案中描述的那样开始,第一个(.*)
吞噬所有角色,第二个和第三个组让它拥有它们,但是它必须匹配一个等号。
显然字符串末尾没有一个字符串,因此组#1逐个返回字符,直到正则表达式中的=
与目标中的=
匹配为止。然后正则表达式引擎开始尝试匹配(\1|\2|\3)+$
并开始真正的乐趣。
组1放弃d
,组2(仍为空)接受它,但正则表达式的其余部分仍然无法匹配。第1组放弃o
和第2组匹配od
,但正则表达式的其余部分仍然无法匹配。因此,随着第三组的参与,他们三人以各种可能的方式切换输入,直到实现整体匹配。据RegexBuddy报道,到达那里需要13426步。
在第一个例子中,贪婪(或缺乏贪婪)并不是真正的因素;唯一可以实现匹配的方法是,如果单词Oh
,My
和God
被捕获,则最终会发生这种情况。甚至哪个群体捕获哪个词都没有关系 - 就像我之前所说的那样,这是先到先得的。
在第二个和第三个例子中,只需要将前缀分成两个块:Oh
和MyGod
。第2组在第二个示例中捕获MyGod
因为它是下一个并且它是贪婪的,就像在第一个示例中一样。在第三个例子中,每当第1组丢弃一个角色时,第2组(不情愿)让第3组取而代之,这样就是最后拥有MyGod
的那个。
答案 2 :(得分:2)
默认情况下,量词并不贪婪,他们只是仓促。在你的例子中,第一个(.*)
将首先吞噬它所能做的一切,而不考虑整个正则表达式的需要。只有这样才能将控制权交给下一部分,如果有必要,它会回馈它刚刚采取的部分或全部内容(即回溯),以便正则表达式的其余部分可以完成其工作。
在这种情况下,这不是必需的,因为其他所有内容都可以合法地匹配零个字符。如果量词真的很贪婪,那么这三个群体就会讨价还价,直到他们尽可能均匀地划分输入;相反,第二组和第三组让第一组保持所需。如果它放在他们面前,他们会接受它,但他们不会为它而战。 (即使它们具有占有量量词,即(.*)(.*+)(.*+)
,也是如此。)
让第二个圆点明星不愿意改变任何东西,但是先切换 。一个不情愿的量词开始只通过匹配,然后交给下一部分。所以(.*?)(.*)(.*)
中的第一组开始时没有匹配任何东西,然后第二组吞噬了所有东西,第三组在回家的路上喊“weee weee weee”。
这是你的额外问题:如果你让所有三个量词都不情愿会怎么样? (提示:在Java中,这是一个API问题,因为它是一个正则表达式问题。)
答案 3 :(得分:0)
正则表达式按顺序工作,这意味着正则表达式只会在他找不到该组的解决方案时才会离开组,并最终进行一些回溯以使该字符串适合下一组。如果执行此正则表达式,您将在第一组中评估所有字符,在下一组中不评估(问号也无关紧要)。
答案 4 :(得分:0)
作为一个简单的一般规则:最左边的量词获胜。因此,只要以下量词识别出纯粹的可选子模式(无论它们是不成熟的),第一个都是全部。