首页 > 解决方案 > 重新 - 负前瞻是否受先前空格数量的影响?

问题描述

给定以下正则表达式:

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)pattr.search(c)

坦率地说,任何帮助将不胜感激。

标签: python-3.xre

解决方案


a匹配但b不匹配的原因是因为空白字符的最后一个贪婪匹配,即\s+之前)和否定的前瞻断言,匹配最长的有效匹配。

对于a,这意味着它匹配的空白字符比人们直觉期望它匹配的要少。这意味着1, 2, 3,5 个空格字符而不是所有 6 个1, 2, 3,you shall not match!. 如果它匹配所有 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,事情就简单多了。您要求一个或多个不跟随的空白字符,如果andyou shall not match!之间只有 1 个空白字符,则无法满足这一点。所以,你没有匹配。1, 2, 3,you shall not match!

对正则表达式的一种可能的更新是添加一个单词边界(根据您的需要,您可能希望 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+))\1(?!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

您可能还想检查支持原子分组和所有格量词的正则表达式模块。


推荐阅读