重新 - 负面前瞻是否受先前空间数量的影响?

Re - Is negative lookahead influenced by the amount of previous spaces?

给定以下正则表达式:

import re
pattr = re.compile(r'(\d+\,\s+\d+\,\s+\d+\,\s+)(?!you shall not match\!)')

和字符串:

a = '1, 2, 3,      you shall not match!'
b = '4, 5, 6, you shall not match!'
c = '7, 8, 9, young neil asdfghj'

我们看到:

>>> pattr.search(a)
<_sre.SRE_Match object; span=(0, 13), match='1, 2, 3,     '>    #With multiple spaces it does match 
>>> pattr.search(b)                                             #With a sinlge space it doesn't found anything; returns None
>>> pattr.search(c)
<_sre.SRE_Match object; span=(0, 19), match='7, 8, 9, '>
>>> 

我需要修改 pattr,使其返回 None pattr.search(a)pattr.search(b)和 return 与上面 pattr.search(c).

相同的输出

如有任何帮助,我们将不胜感激。

a 匹配而 b 不匹配的原因是因为对空白字符的最后一次贪婪匹配,即 ) 之前的 \s+ 和负先行断言, 匹配最长 有效 匹配。

对于a,这意味着它匹配的空白字符少于我们凭直觉期望匹配的空白字符。这意味着 1, 2, 3, 和 5 个空白字符,而不是将 1, 2, 3,you shall not match! 分开的全部 6 个。如果它匹配所有 6 个,那么它就不会是一个 有效 匹配,因为你要求 1, 2, 3, 后跟一系列空白字符而不是 you shall not match! .所以,匹配是可能的,这就是你得到的。

>>> pattr = re.compile(r'(\d+\,\s+\d+\,\s+\d+\,\s+)(?!you shall not match!)')
>>> pattr.match(a)
<_sre.SRE_Match object; span=(0, 13), match='1, 2, 3,     '> # 5 whitespaces matched
>>>
>>> a
'1, 2, 3,      you shall not match!' # ... but a has 6

对于b,事情就简单多了。您要求一个或多个未跟在 you shall not match! 之后的空白字符,如果 1, 2, 3,you shall not match! 之间只有 1 个空白字符,则无法满足这一要求。所以,你找不到匹配项。

您的正则表达式的一个可能更新是添加单词边界(根据您的需要,您可能希望 a. 将 \s* 替换为 \s+ 或 b. 包含 \b 括号内,即组):

>>> pattr = re.compile(r'(\d+\,\s+\d+\,\s+\d+\,\s*)\b(?!you shall not match!)')
>>> pattr.match(a)
>>> pattr.match(b)
>>> pattr.match(c)
<_sre.SRE_Match object; span=(0, 9), match='7, 8, 9, '>
>>>
>>> # a and b do not match and c matches what it did with you regular expression
>>>
>>> pattr = re.compile(r'(\d+\,\s+\d+\,\s+\d+\,\s+)(?!you shall not match!)')
>>> pattr.match(c)
<_sre.SRE_Match object; span=(0, 9), match='7, 8, 9, '>

另一个可能的更新是模拟“原子匹配”或“占有匹配”:

>>> pattr = re.compile(r'(?=(\d+\,\s+\d+\,\s+\d+\,\s+))(?!you shall not match!)')
>>> pattr.match(a)
>>> pattr.match(b)
>>> pattr.match(c)
<_sre.SRE_Match object; span=(0, 9), match='7, 8, 9, '>
>>> # a and b do not match and c matches what it did with you regular expression

您可能还想查看支持原子分组和所有格量词的 regex module