我正在学习正则表达式并正在尝试环视,但我对这些表达式的放置顺序很困惑,就像我正在尝试以下
b(?!a)
以上应该是b not followed by a
。如果我把它放在那就好了
(?!a)b
这匹配b无论来自哪里..
现在,如果我做这样的事情
^(?!.*\bMy Links\b).*$
在上面,负向前瞻是在消耗字符的字符串之前..现在为什么是
所以放置负前瞻的规则是什么?没有讨论整个模式中的位置。请解释一下吗?
答案 0 :(得分: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
在当前位置之前的那个根本不重要。 b满足前面的负面看,所以我们去
cafeba^be (?!a)^b
这就过去了。最后的选择失败了。
在第三个示例中,负向前瞻是在最开始,但以.*
开头。因此,如果没有任何字符序列后跟一个单词边界,则后面跟着My Links
后跟一个单词边界。如果通过,则继续使用整个字符串而不捕获任何内容。所以,它相当于这个字符串是否包含My Links
被字边界包围?只需尝试查找\bMy Links\b
并失败就会稍快一些。
答案 1 :(得分:1)
您必须知道,^
,$
或\b
的外观为“零宽度”,这意味着它只代表光标位置 “字符”。在环视机制中,只需通过在进入环视部分之前使正则表达式引擎记住光标位置,然后将部分光标重置为之前记忆的位置即可完成。
现在,如果您想检查某个字母(在您的情况下为b
)是否没有其他字母(在您的情况下为a
),则需要将其写为b(?!a)
。这将使正则表达式首先找到b
(将在b
之后设置光标),然后在a
之后测试字母。
如果你将(?!a)b
正则表达式写成每个光标位置(假设它在b
之前)将进行前瞻测试(因此它会暂时将光标移动到下一个位置,读取在它之前的字符并检查它是否不是a
。由于光标在b
之前,它将接受b
不是a
并将光标移回{{1}之前现在在预测之后,测试正则表达式引擎将移动到tegex模式的下一部分(它将检查下一个字符是否为b
),并且因为光标在b
匹配之前将被找到。
因此,如果b
(?!a)b
每个b
都可以,那么b
无法a