2

我正在学习正则表达式并尝试环顾四周,但我对这些表达式的放置顺序感到困惑,就像我正在尝试以下内容一样

 b(?!a)

以上应该是意思b not followed by a。现在可以了,如果我放置它

 (?!a)b

这匹配 b 无论 a 来自哪里..

现在如果我做这样的事情

    ^(?!.*\bMy Links\b).*$

在上面的否定前瞻是在消耗字符的字符串之前..现在为什么

那么放置负前瞻的规则是什么。没有讨论整个模式中的位置。请解释一下?

4

2 回答 2

1

我将使用插入符号^来表示正在搜索的字符串和正则表达式中的当前搜索位置。采取正则表达式b(?!a),并假设我通过搜索cafebabe。系统试图找到b第一个。前四个字母失败,它到达第一个b

cafe^babe    ^b(?!a)

b 匹配,因此它在正则表达式中继续:

cafeb^abe    b^(?!a)

但是负前瞻失败了;下一个字符是 a。因此,正则表达式重置,我们转到字符串中的下一个位置:

cafeb^abe    ^b(?!a)

这失败了,它继续

cafeba^be    ^b(?!a)

b 匹配,所以

cafebab^e    b^(?!a)

并且字符串通过负前瞻,所以我们到达:

cafebab^e    b(?!a)^

我们通过了。

现在,使用第二个表达式。请记住,这是消极的前瞻,而不是消极的往后看。

^cafebabe    ^(?!a)b

c 通过,所以它继续

^cafebabe    (?!a)^b

失败了。

重置正则表达式并推进字符串给出:

c^afebabe    ^(?!a)b

因为负前瞻失败了,所以失败了。

接下来的两个失败,就像第一个失败一样,留下:

cafe^babe    ^(?!a)b

负前瞻成功,所以我们继续

cafe^babe    (?!a)^b

成功了。假设你走得更远。下一封信失败了,就像第二封信一样:

cafeb^abe    ^(?!a)b

在那之后

cafeba^be    ^(?!a)b

a 在当前位置之前并不重要。b 满足负前瞻,所以我们去

cafeba^be    (?!a)^b

这通过了。最后的选择失败了。

添加

在您的第三个示例中,负前瞻位于最开始,但以.*. 因此,如果没有任何字符序列后跟单词边界,然后是单词边界,则它通过My Links。如果通过了,那么它将继续消耗整个字符串而不捕获任何内容。所以,它相当于这个字符串是否包含My Links被单词边界包围?简单地尝试查找\bMy Links\b和失败会稍微快一些。

于 2013-05-26T20:32:11.407 回答
1

您必须知道环视是“零宽度” ^$或者\b这意味着它只代表光标的位置而不是“字符”。在环视机制中,只需让正则表达式引擎在进入环视部分之前记住光标的位置,然后在该部分光标将重置到这个先前记住的位置。

现在,如果您想检查某个字母(在您的情况下b)之后是否没有其他字母(在您的情况下a),您需要将其写为b(?!a). 这将使正则表达式首先找到b(它将在 之后设置光标b),然后在它之后测试字母a

如果你将它写(?!a)b为每个光标位置的正则表达式(假设它是 before b)将进行前瞻测试(所以它会临时将光标移动到下一个位置,读取它之前的字符并检查它是否不是a。因为光标是之前b它会接受b不是a并将光标移回之前b。现在,在前瞻测试之后,正则表达式引擎将移动到 tegex 模式的下一部分(它将检查下一个字符是否为b),并且由于光标在b匹配之前将被发现。

所以万一(?!a)b每个都可以b,因为没有办法ba

于 2013-05-26T21:22:17.027 回答