3
>>> d = "Batman,Superman"
>>> m = re.search("(?<!Bat)\w+",d)
>>> m.group(0)
'Batman'

为什么 group(0) 不匹配超人?这个环视教程说:

(?<!a)b 匹配前面没有“a”的“b”,使用否定的lookbehind

4

5 回答 5

6

Batman不是直接在前面Bat所以首先匹配。事实上,两者都不是Superman;在您的字符串之间有一个逗号可以很好地允许该 RE 匹配,但无论如何都不匹配,因为它可以在字符串中更早地匹配。

也许这会更好地解释:如果字符串是Batman并且您开始尝试从 匹配m,则 RE 将不匹配直到后面的字符(匹配an),因为这是字符串中唯一以 . 开头的位置Bat

于 2011-06-16T20:36:36.030 回答
1

从手册:

以否定后向断言开头的模式可能在被搜索的字符串的开头匹配。

http://docs.python.org/library/re.html#regular-expression-syntax

于 2011-06-16T20:38:19.613 回答
1

简单来说,正则表达式引擎从字符串的左侧开始并逐渐向右移动,试图匹配您的模式(将其想象为光标在字符串中移动)。在环视的情况下,在光标的每个停止处,都会断言环视,如果为真,引擎会继续尝试进行匹配。一旦引擎可以匹配您的模式,它就会返回一个匹配项。

在字符串的位置 0(即Bin之前Batman),断言成功,因为Bat在当前位置之前不存在 - 因此,\w+可以匹配整个单词Batman(请记住,正则表达式本质上是贪婪的- 即。将匹配尽可能多可能的)。

有关引擎内部结构的更多信息,请参阅此页面


为了实现你想要的,你可以使用类似的东西:

\b(?!Bat)\w+

在此模式中,引擎将匹配单词边界( \b) 1,后跟一个或多个单词字符,并断言单词字符不以 开头Bat。使用前瞻而不是后向,因为在这里使用后向会与原始模式存在相同的问题;它会在紧跟单词边界的位置之前查找,并且由于已经确定光标之前的位置是单词边界,因此否定向后查找总是会成功。

1请注意,单词边界匹配 and 之间的边界\w\W即 between [A-Za-z0-9_]and 任何其他字符;它也匹配^and$ 锚点)。如果您的边界需要更复杂,您将需要一种不同的方式来锚定您的模式。

于 2011-06-16T20:38:57.007 回答
1

您正在寻找\w+前面没有“Bat”的第一组一个或多个字母数字字符 ( )。蝙蝠侠是第一个这样的比赛。(请注意,否定的后向断言可以匹配字符串的开头。)

于 2011-06-16T20:42:01.517 回答
1

为了做你想做的事,你必须约束正则表达式来'man'专门匹配;否则,正如其他人所指出的那样,\w贪婪地匹配任何东西,包括'Batman'. 如:

>>> re.search("\w+(?<!Bat)man","Batman,Superman").group(0)
'Superman'
于 2011-06-16T20:50:50.063 回答