正则表达式中的负面回顾
Negative lookbehind in regex
(注意:不是 Why can't you use repetition quantifiers in zero-width look behind assertions 的重复;见 post 的结尾。)
我正在尝试编写一个匹配 B 的 grep -P
(Perl) 正则表达式,当它前面没有 A 时——不管中间是否有空格。
所以,我尝试了这种负面回顾,并在 regex101.com:
中进行了测试
(?<!A)\s*B
这会导致 "AB" 无法匹配,这很好,但是 "A B" 确实会导致匹配,这不是我想要的。
我不太确定这是为什么。它与 \s* 匹配空字符串 "" 的事实有关,因此你可以说 A 和 B 之间存在 \s* 的无限匹配。但是为什么这会影响 "A B" 但不是 "AB"?
以下正则表达式是否是正确的解决方案?如果是,为什么它能解决问题?
(?<![A\s])\s*B
我之前post编辑过这个问题,但它被错误地标记为重复问题。我正在寻找的可变长度的东西是比赛的一部分,而不是负面回顾本身的一部分——所以这与另一个问题完全不同。是的,我可以将 \s* 放在负面回顾中,但我没有这样做(并且不支持这样做,正如另一个问题所解释的那样)。另外,我特别感兴趣 为什么上面我 post 的备用正则表达式有效 ,因为我知道它有效,但我不确定为什么。另一个问题没有帮助回答这个问题。
But why does this affect "A B" but not "AB"?
正则表达式在 位置 处匹配,将其视为字符之间会很有帮助。在“A B”中有一个位置(在 space 之后和 B 之前),其中 (?<!A)
成功(因为前面没有 A;而是 space),并且\s*B
成功(\s*
匹配空串,B
匹配B),所以整个模式成功。
在“AB”中没有这样的位置。 \s*B
唯一可以匹配的地方(紧接在 B 之前),也是紧接在 A 之后,因此 (?<!A)
无法成功。没有一个位置可以同时满足两者,所以整个模式是无法成功的。
Is the following regex a proper solution, and if so, why exactly does it fix the problem?
(?<![A\s])\s*B
这是可行的,因为 (?<![A\s])
不会在 A 或 之后立即成功 space。所以现在lookbehind禁止任何在它之前有spaces的匹配位置。如果 B 之前有 个 space,它们必须被模式的 \s*
部分消耗,并且匹配位置必须在它们之前。如果那个位置 also 前面没有 A,lookbehind 可以成功并且整个模式可以匹配。
这个技巧之所以成为可能,是因为 \s
是一个固定宽度的模式,匹配非空 [=] 内的 每个 位置12=]匹配。它不能扩展到(非)A 和 B 之间 any 模式的一般情况。
(注意:不是 Why can't you use repetition quantifiers in zero-width look behind assertions 的重复;见 post 的结尾。)
我正在尝试编写一个匹配 B 的 grep -P
(Perl) 正则表达式,当它前面没有 A 时——不管中间是否有空格。
所以,我尝试了这种负面回顾,并在 regex101.com:
中进行了测试(?<!A)\s*B
这会导致 "AB" 无法匹配,这很好,但是 "A B" 确实会导致匹配,这不是我想要的。
我不太确定这是为什么。它与 \s* 匹配空字符串 "" 的事实有关,因此你可以说 A 和 B 之间存在 \s* 的无限匹配。但是为什么这会影响 "A B" 但不是 "AB"?
以下正则表达式是否是正确的解决方案?如果是,为什么它能解决问题?
(?<![A\s])\s*B
我之前post编辑过这个问题,但它被错误地标记为重复问题。我正在寻找的可变长度的东西是比赛的一部分,而不是负面回顾本身的一部分——所以这与另一个问题完全不同。是的,我可以将 \s* 放在负面回顾中,但我没有这样做(并且不支持这样做,正如另一个问题所解释的那样)。另外,我特别感兴趣 为什么上面我 post 的备用正则表达式有效 ,因为我知道它有效,但我不确定为什么。另一个问题没有帮助回答这个问题。
But why does this affect "A B" but not "AB"?
正则表达式在 位置 处匹配,将其视为字符之间会很有帮助。在“A B”中有一个位置(在 space 之后和 B 之前),其中 (?<!A)
成功(因为前面没有 A;而是 space),并且\s*B
成功(\s*
匹配空串,B
匹配B),所以整个模式成功。
在“AB”中没有这样的位置。 \s*B
唯一可以匹配的地方(紧接在 B 之前),也是紧接在 A 之后,因此 (?<!A)
无法成功。没有一个位置可以同时满足两者,所以整个模式是无法成功的。
Is the following regex a proper solution, and if so, why exactly does it fix the problem?
(?<![A\s])\s*B
这是可行的,因为 (?<![A\s])
不会在 A 或 之后立即成功 space。所以现在lookbehind禁止任何在它之前有spaces的匹配位置。如果 B 之前有 个 space,它们必须被模式的 \s*
部分消耗,并且匹配位置必须在它们之前。如果那个位置 also 前面没有 A,lookbehind 可以成功并且整个模式可以匹配。
这个技巧之所以成为可能,是因为 \s
是一个固定宽度的模式,匹配非空 [=] 内的 每个 位置12=]匹配。它不能扩展到(非)A 和 B 之间 any 模式的一般情况。