Python正则表达式中的B + vs [\ B] + vs [^ \ b] +

时间:2016-07-17 18:07:33

标签: python regex

我遇到了一个在回答SO问题时我不理解的问题。我已经创建了一个简化示例来说明问题:

情景:

我正在测试两个令牌(不是随机的英语单词!)在一个字符串中至少有一段距离。在这个例子中,我们有一个动物清单,我们想确保绵羊和狼之间至少有三只其他动物(或者那里有麻烦)。以下代码有效:

import re

safe_distance = re.compile(r"sheep (\b[^\b]+\b ){3,}wolf")

animal_arrangements = [
    "dog sheep hen wolf fox cat ox",  # one between
    "dog sheep hen fox wolf cat ox",  # two between
    "dog sheep hen fox cat wolf ox",  # three between
    "dog sheep hen fox cat ox wolf"   # four between
]

for i, animal_arrangement in enumerate(animal_arrangements):

    if safe_distance.search(animal_arrangement):
        print(i + 1, "All is peaceful.")
    else:
        print(i + 1, "Sheep and wolf too close!")

问题:

在上述模式中,使用:

[^\b]+  # works fine
\B+     # causes a regex compilation error "nothing to repeat"
[\B]+   # runs but produces wrong answers
\w+     # yes, this does work, probably best, but not related to my question

为何与众不同?我不需要更好地解决绵羊/狼的放置问题 - 我只是试图理解为什么这三个一个或多个不是一个词边界的变体< / em>模式产生不同的结果。

我知道\b,就像一个锚点,并不代表一个角色,而且模板被认真考虑(与使用`\ w&#39;相比),但为什么差异?

2 个答案:

答案 0 :(得分:3)

  • \B+会导致错误,因为重复边界没有意义 - 一个边界与两个边界相同。你错误地做了这个,所以这个错误是有道理的。
  • [\B]+是完全不同的东西。 (大多数)转义序列在字符类中不起作用,这就是为什么这是一个与字符\B匹配的字符集,因此显然可以重复此操作。

答案 1 :(得分:3)

当您尝试量化一个零宽度断言的特殊正则表达式运算符时,\B+模式不会导致重复错误,这是一个常见错误。其中任何一项 - (*|*\b+\B+都会导致此错误。重复零宽度断言是没有意义的,因为它不消耗任何字符并且正则表达式索引保持在相同位置。请注意,a{1,2}+f*+(Python re不支持的占有量词)导致另一个但类似的错误 - 多次重复

现在,\b\B不能在字符类中使用。见re Python reference

  

请注意,\b用于表示字边界,并且仅在字符类中表示“退格”。   ...   在字符范围内,\b表示退格符,以便与Python的字符串文字兼容。

另外,仅供参考,

  

\number
  ...在字符类的[]内,所有数字转义都被视为字符。

同样,您无法在字符类<{1}}内使用\B\A\Z反向引用 < / em>的。他们只是失去了他们特殊的正则表达式意义,并被视为Python认为正确的。实际上,由于Python将无效转义序列解析为\1 + char,因此 \仅匹配[\B]个字符,因为B正在转义文字符号且符号为这样匹配。因此,

\

outputs ['BBB', 'B'] only

print(re.findall(r'[\B]+', "BBB \\Bash")) 只匹配所有不是退格字符的字符:

r"[^\b]+"

输出['bbb \\bash', 'aaa']