正则表达式中的负面看法

时间:2017-03-29 21:58:09

标签: regex perl grep negative-lookbehind

(注意:不是Why can't you use repetition quantifiers in zero-width look behind assertions的副本;请参阅帖子的结尾。)

我正在尝试编写一个与B匹配的grep -P(Perl)正则表达式,当它不在A之前时 - 无论是否存在插入的空格。

所以,我尝试了这种消极的外观,并在regex101.com中进行了测试:

(?<!A)\s*B

这会导致“AB”不匹配,这很好,但“A B”会导致匹配,这不是我想要的。

我不确定为什么会这样。它与\ s *匹配空字符串“”的事实有关,你可以说A和B之间存在\ s *的无穷大匹配。但为什么这会影响“AB”但是不是“AB”?

以下正则表达式是否是正确的解决方案,如果是这样,为什么它确实解决了这个问题?

(?<![A\s])\s*B

之前我发布了此内容,并将其错误地标记为重复的问题。我正在寻找的可变长度的东西是比赛的一部分,而不是负面观察本身的一部分 - 所以这与另一个问题完全不同。是的,我可以把\ s *放在负面的看后面,但我还没有这样做(并且不支持这样做,正如另一个问题所解释的那样)。另外,我特别感兴趣为什么我上面发布的备用正则表达式工作,因为我知道它有效,但我不确定为什么。另一个问题没有帮助回答这个问题。

1 个答案:

答案 0 :(得分:4)

  

但为什么这会影响&#34; A B&#34;但不是&#34; AB&#34;?

正则表达式匹配位置,这有助于将其视为在字符之间。在&#34; A B&#34;有一个位置(在空格之后和B之前)(?<!A)成功的位置(因为前面没有A;而是空格而已),\s*B成功( \s*匹配空字符串,B匹配B),因此整个模式成功。

在&#34; AB&#34;没有这样的立场。 \s*B可以匹配的唯一位置(紧接在B之前)也紧跟在A之后,因此(?<!A)无法成功。没有任何职位可以满足两者,因此整体模式不会成功。

  

以下正则表达式是否是正确的解决方案,如果是这样,为什么它确实解决了这个问题?

     

(?<![A\s])\s*B

这是有效的,因为(?<![A\s])在空格后的A 之后不会立即成功。所以现在lookbehind禁止任何在它之前有空格的匹配位置。如果 在B之前有任何空格,则必须由模式的\s*部分使用,匹配位置必须在它们之前。如果该位置在它之前没有A,则后视可以成功并且整个模式可以匹配。

这是一个诀窍,因为\s是一个固定宽度的模式,匹配在非空{{1}内的每个位置}} 比赛。它不能扩展到(非)A和B之间任何模式的一般情况。