>>> d = "Batman,Superman"
>>> m = re.search("(?<!Bat)\w+",d)
>>> m.group(0)
'Batman'
为什么group(0)没有匹配到Superman?这篇反向引用教程解释道:
(?
>>> d = "Batman,Superman"
>>> m = re.search("(?<!Bat)\w+",d)
>>> m.group(0)
'Batman'
Batman
并不是直接跟在Bat
后面的,因此首先匹配的是它。实际上,Superman
也不是;在您的字符串中有一个逗号,这足以允许RE匹配,但它仍然没有匹配,因为可能在字符串中更早地匹配。
也许这样会更好地解释:如果字符串是Batman
,并且您从m
开始尝试匹配,那么RE将不会匹配,直到字符之后(给出匹配an
),因为这是字符串中唯一一个前面跟着Bat
的位置。
来自手册:
以负向回顾断言开头的模式可能会匹配正在搜索的字符串的开头。
http://docs.python.org/library/re.html#regular-expression-syntax
B
之前),断言成功,因为当前位置之前不存在“Bat”,因此\w+
可以匹配整个单词“Batman”(请记住,正则表达式本质上是“贪心”的 - 即将尽可能多地匹配)。\b(?!Bat)\w+
在这个模式中,引擎将匹配一个单词边界(\b
)1,然后是一个或多个单词字符,并断言这些单词字符不以Bat
开头。使用了前瞻而不是后顾,因为在这里使用后顾会和您原来的模式有同样的问题;它会在紧跟在单词边界之后的位置之前查找,而且由于已经确定光标之前的位置是单词边界,否定的后顾会始终成功。
1注意,单词边界匹配\w
和\W
之间的边界(即[A-Za-z0-9_]
与任何其他字符之间的边界;它还匹配^
和$
锚点)。如果您的边界需要更复杂的情况,您将需要一种不同的方式对模式进行定位。
你正在寻找第一组一个或多个字母数字字符(\w+
),它不是由'Bat'前置。Batman是第一个这样的匹配项。(请注意,负回顾断言可以匹配字符串的开头。)
'man'
;否则,就像其他人指出的那样,\w
会贪婪地匹配任何内容,包括'Batman'
。代码如下:>>> re.search("\w+(?<!Bat)man","Batman,Superman").group(0)
'Superman'