任何人都可以一步一步解释我为什么正则表达式失败了:
<.++>
使用此字符串进行比较:<em>
在懒惰或贪婪量词中找到相同的字符串,但在这种情况下 涉及哪些步骤?
我使用Java正则表达式。
答案 0 :(得分:12)
占有量词,尽可能地贪婪地匹配并且不会退缩,即使这样做也会使整体比赛成功。
在您的示例中,正则表达式中的<
与字符串中的<
匹配,然后.++
匹配字符串的其余部分em>
。您的正则表达式中仍然有>
,但字符串中没有字符可供匹配(因为.++
全部消耗了它们)。所以比赛失败了。
如果量词是贪婪的,即如果它是.+
而不是.++
,那么正则表达式引擎会尝试将.+
匹配的部分减少一个字符,只需em
,然后重试。这次匹配会成功,因为字符串中会留下>
,以便匹配正则表达式中的>
。
编辑:懒惰的量词会像贪婪的量词一样反过来。懒惰量词将首先尝试匹配单个字符,在这种情况下只是e
,而不是尝试匹配字符串的其余部分并逐个字符地退出。如果这不允许完整正则表达式匹配(这不会在这里,因为你在正则表达式中>
试图匹配字符串中的m
),懒惰的量词会移动最多匹配两个字符em
。然后正则表达式中的>
将与字符串中的>
对齐,匹配将成功。但是,如果它没有成功,那么延迟量词将最多移动三个字符,依此类推。
答案 1 :(得分:4)
Possessive quantifier会阻止回溯 - 因此.++
部分会与剩余的字符串em>
匹配,同时也会占用最后一个>
。
因此正则表达式的最后>
没有匹配且正则表达式失败。
就像贪婪的量词一样,占有量词会尽可能多地重复令牌。与贪婪的量词不同,它不会因为引擎回溯而放弃匹配。通过占有量词,交易全部或全无。您可以通过在其后面添加额外的
+
来使量词占有。
答案 2 :(得分:3)
首先让我们考虑像<.+>
这样的模式如何与<em>
匹配:
<
与输入中的<
匹配。.+
匹配输入中的em>
(因为它贪婪,它首先匹配尽可能多的.
)
>
不匹配,因为输入中没有其他字符.+
回溯并且必须少一个.
;所以.+
现在匹配em
>
现在与输入中的>
匹配。相比之下,这是<.+?>
与<em>
匹配的方式:
<
与输入中的<
匹配。.+?
匹配输入中的e
(因为它不情愿,但必须至少有一个.
)
>
不匹配,因为输入的其余部分为m>
.+
回溯并且必须再匹配.
;所以.+?
现在匹配em
>
现在与输入中的>
匹配。请注意,在上述任何一种情况下,.+
或.+?
必须回溯才能匹配>
。这就是为什么<.++>
永远匹配<em>
的原因,因为这是发生的事情:
<
与输入中的<
匹配.++
在输入中匹配尽可能多的.
,并且将拥有此匹配
.++
能够匹配em>
>
永远不会匹配,因为任何>
都会被.++
吞噬
.++
不会通过回馈>
至少有机会匹配的模式是<[^>]++>
。与<em>
匹配时:
<
与输入中的<
匹配[^>]++
在输入中占用[^>]
所占数量(即>
以外的任何内容)
em
>
现在可以与输入中的>
匹配尽可能实际,您应该避免在模式中使用.*?
/ .*
。 .
太灵活了,因为它匹配(差不多!)任何字符,这会导致不必要的回溯和/或匹配。
只要适用,您应使用否定字符类而不是.