>>> d = "Batman,Superman"
>>> m = re.search("(?<!Bat)\w+",d)
>>> m.group(0)
'Batman'
为什么组(0)不匹配超人? This lookaround tutorial说:
(?&lt;!a)b匹配不是的“b” 前面是“a”,使用否定 回顾后发
答案 0 :(得分:6)
Batman
{{}} 事实上,Bat
也不是;在你的字符串中间有一个逗号,它可以很好地允许RE匹配,但是无论如何都不匹配,因为它可以在字符串的前面匹配。
也许这会更好地解释:如果字符串是Superman
并且您开始尝试匹配Batman
,则RE将不会匹配,直到后面的字符(给出m
的匹配项,因为这是字符串中唯一以an
开头的位置。
答案 1 :(得分:1)
从手册:
以负面开头的模式 lookbehind断言可能匹配 字符串的开头 搜索。
http://docs.python.org/library/re.html#regular-expression-syntax
答案 2 :(得分:1)
在一个简单的层面上,正则表达式引擎从字符串的左侧开始并逐渐向右移动,尝试匹配您的模式(将其视为移动通过字符串的光标)。在外观的情况下,在光标的每个停止处,断言是断言的,如果是,则引擎继续尝试进行匹配。一旦引擎可以匹配您的模式,它将返回匹配。
在你的字符串的第0位(即B
中的Batman
之前),断言成功,因为Bat
在当前位置之前不存在 - 因此,{{ 1}}可以匹配整个单词\w+
(请记住,正则表达式本质上是贪婪 - 即尽可能匹配。)
有关引擎内部的详细信息,请参阅this page。
为了达到你想要的效果,你可以使用类似的东西:
Batman
在此模式中,引擎将匹配word boundary(\b(?!Bat)\w+
) 1 ,后跟一个或多个单词字符,并断言单词字符不从\b
开始。使用 lookahead 而不是 lookbehind ,因为在这里使用lookbehind会遇到与原始模式相同的问题;它会直接跟在单词边界之后的位置之前,因为已经确定光标前的位置是一个单词边界,所以负面的后观将始终成功。
1 请注意,单词边界与Bat
和\w
之间的边界匹配(即\W
与任何其他字符之间的边界;它也匹配{{ 1}}和[A-Za-z0-9_]
anchors)。如果你的边界需要更复杂,你需要一种不同的方式来锚定你的模式。
答案 3 :(得分:1)
您正在寻找第一组一个或多个字母数字字符(\w+
),前面没有'Bat'。蝙蝠侠是第一场这样的比赛。 (注意,负向lookbehind断言可以匹配字符串的开头。)
答案 4 :(得分:1)
要做你想做的事,你必须将正则表达式限制为特别匹配'man'
;否则,正如其他人所指出的那样,\w
贪婪地匹配任何内容,包括'Batman'
。如:
>>> re.search("\w+(?<!Bat)man","Batman,Superman").group(0)
'Superman'