我有以下字符串: <div data-sticky-container >
<div id="mobileMenu" class="title-bar" data-responsive-toggle="main-menu" data-hide="medium"
data-sticky data-options="marginTop:0;" style="width:100%"
data-top-anchor="top">
<button class="menu-icon" type="button" data-toggle="main-menu"></button>
<div class="title-bar-title">Menu</div>
</div>
</div>
<div data-sticky-container>
<div class="top-bar" id="main-menu"
data-sticky data-options="marginTop:0;" style="width:100%"
data-top-anchor="1">
<div class="top-bar-left">
<ul class="dropdown menu" data-dropdown-menu>
<!--links here-->
</ul>
</div>
</div>
</div>
。我希望将AB中的文本与第一次出现的CD相匹配。受this回答的启发,我创建了以下正则表达式模式:
"text before AB000CD000CD text after"
我在https://regex101.com/中检查了结果,输出为:
AB((?!CD).)*CD
看起来它能满足我的需求。但是我不明白它为什么会起作用。我的理解是我的模式应首先匹配AB,然后是任何未跟随CD的角色,然后是CD本身。但遵循这个逻辑,结果不应该包括000,而只包括00,因为最后的零实际上是CD。我的解释错了吗?
答案 0 :(得分:3)
AB((?!CD).)*CD
匹配AB
,然后匹配任何未启动CD
字符序列的字符,然后CD
。那就是你错误地说“没有跟着CD”。请注意,负向前瞻位于 .
之前。
此外,当否定部分与尾部边界相同时使用tempered greedy token是没有意义的,只需使用惰性点匹配模式AB(.*?)CD
。如果您不想在AB
和AB
之间匹配CD
(初始边界),则需要使用该构造。 AB((?:(?!AB).)*?)CD
(这是最常见的用例)。
请参阅rexegg.com reference了解何时使用它:
假设我们的老板现在告诉我们,我们仍然希望匹配并包括
{END}
,但我们还需要避免单步执行{MID}
部分(如果存在)。从懒惰的点星版本开始,以确保我们匹配{END}
分隔符,然后我们可以调整点以确保它不会翻转{MID}
:
{START}(?:(?!{MID}).)*?{END}
如果必须避免使用更多短语,我们只需将它们添加到我们的脾气点:
{START}(?:(?!{MID})(?!{RESTART}).)*?{END}
另外,see this thread。