我正在学习正则表达式并尝试环顾四周,但我对这些表达式的放置顺序感到困惑,就像我正在尝试以下内容一样
b(?!a)
以上应该是意思b not followed by a
。现在可以了,如果我放置它
(?!a)b
这匹配 b 无论 a 来自哪里..
现在如果我做这样的事情
^(?!.*\bMy Links\b).*$
在上面的否定前瞻是在消耗字符的字符串之前..现在为什么
那么放置负前瞻的规则是什么。没有讨论整个模式中的位置。请解释一下?
我正在学习正则表达式并尝试环顾四周,但我对这些表达式的放置顺序感到困惑,就像我正在尝试以下内容一样
b(?!a)
以上应该是意思b not followed by a
。现在可以了,如果我放置它
(?!a)b
这匹配 b 无论 a 来自哪里..
现在如果我做这样的事情
^(?!.*\bMy Links\b).*$
在上面的否定前瞻是在消耗字符的字符串之前..现在为什么
那么放置负前瞻的规则是什么。没有讨论整个模式中的位置。请解释一下?
我将使用插入符号^
来表示正在搜索的字符串和正则表达式中的当前搜索位置。采取正则表达式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
和失败会稍微快一些。
您必须知道环视是“零宽度” ^
,$
或者\b
这意味着它只代表光标的位置而不是“字符”。在环视机制中,只需让正则表达式引擎在进入环视部分之前记住光标的位置,然后在该部分光标将重置到这个先前记住的位置。
现在,如果您想检查某个字母(在您的情况下b
)之后是否没有其他字母(在您的情况下a
),您需要将其写为b(?!a)
. 这将使正则表达式首先找到b
(它将在 之后设置光标b
),然后在它之后测试字母a
。
如果你将它写(?!a)b
为每个光标位置的正则表达式(假设它是 before b
)将进行前瞻测试(所以它会临时将光标移动到下一个位置,读取它之前的字符并检查它是否不是a
。因为光标是之前b
它会接受b
不是a
并将光标移回之前b
。现在,在前瞻测试之后,正则表达式引擎将移动到 tegex 模式的下一部分(它将检查下一个字符是否为b
),并且由于光标在b
匹配之前将被发现。
所以万一(?!a)b
每个都可以b
,因为没有办法b
a