Python re:否定正则表达式的一部分
也许这个问题听起来有点傻,但虽然谷歌找到了很多类似的情况,我还是没能找到这个确切的情况:什么样的正则表达式可以匹配所有不包含特定字符串的字符串。例如,我想匹配任何不包含 'foo_' 的字符串。
re.match('(?<!foo_).*', 'foo_bar')
这个会返回匹配结果。而
re.match('(?<!foo_)bar', 'foo_bar')
这个则不会。
我试过非贪婪版本:
re.match('(?<!foo_).*?', 'foo_bar')
还是会返回匹配结果。
如果我在后面加上更多字符,
re.search('(?<!foo_)b.*', 'foo_bar')
它就返回 None,但如果目标字符串后面有更多字符:
re.search('(?<!foo_)b.*', 'foo_barbaric')
它又会返回匹配结果。
我故意没有在正则表达式开头加上 .* 或 .*?。但加上后也会出现同样的情况。
有没有人知道为什么会有这种奇怪的行为?(我需要这个作为一个单一的正则表达式 - 以便用户输入)。
3 个回答
0
我觉得你可以通过一个条件语句来解决这个问题,这样设计起来会更简单。
如果我们知道你具体想要实现什么,那就更好了。
为什么不试试这样做呢:
if not re.match("foo", something):
do_something
else:
print "SKipping this"
3
试试这个模式:
^(?!.*foo_).*
这个模式使用了 ^
这个特殊符号,它的作用是从字符串的开头开始匹配。接着,它使用了一种叫做负向前瞻的技巧,来检查字符串中是否有 "foo_" 这个部分。如果有的话,匹配就会失败。
因为你给出的例子中用了 re.match()
和 re.search()
两种方法,上面的模式在这两种方法中都能用。不过,当你使用 re.match()
的时候,可以放心地不使用 ^
这个符号,因为它默认就是从字符串的开头开始匹配。而 re.search()
则是可以在字符串的任何位置进行匹配。
4
你在使用“向后查找”的方法,但其实应该用“向前查找”的方法:
re.match(r"(?!.*foo_).*", "foo_bar")
这样做是有效的(也就是说,不会匹配到)。
(?!.*foo_)
的意思是“确认从当前字符串的位置开始,无法匹配到.*foo_
”。因为你使用的是re.match()
,所以这个位置自动被定义为字符串的开头。