Python正则表达式中的上一组匹配

时间:2014-03-12 18:09:39

标签: python regex

我尝试捕获看起来像%a%b等的字符串片段,并用一些值替换它们。此外,我希望能够通过键入%来转义%%字符。

在示例字符串%d%%f%x%%%g中,我想匹配%d%%f%x%%%g%d%x%g)。

我的正则表达式如下:

(?:[^%]|^)(?:%%)*(%[a-z])
  • (?:[^%]|^) - 匹配行的开头或与%不同的字符
  • (?:%%)* - 匹配0次或多次%%次出现(已转义%
  • (%[a-z]) - 与%a%b等模式的正确匹配

添加前两个元素以支持%字符的转义。

但是,在示例字符串上运行regexp时,找不到最后一个片段(%g):

>>> import re
>>> pat = re.compile("(?:[^%]|^)(?:%%)*(%[a-z])")
>>> pat.findall("%d%%f%x%%%g")
['%d', '%x']

但在%%%g之前添加一个字符后,它开始正常工作:

>>> pat.findall("%d%%f%x %%%g")
['%d', '%x', '%g']

在与x组匹配后,[^%]似乎再次与(%[a-z])不匹配。如何更改正则表达式以强制它再次检查上一个匹配的最后一个字符?我读到了\G,但它没有帮助。

3 个答案:

答案 0 :(得分:3)

为什么它没有选择%g

要选择%g,必须先选择%%。甚至在此之前它必须具有non-%字符,或者在字符串的开头。因此,x%%%g可能与您匹配。但是在先前的匹配期间(即打印x时)选择了%x

简单来说,你的正则表达式匹配有重叠。所以你可以用下面的方法克服这一点。我将你的正则表达式放在(?= ... )

pat = re.compile("(?=(?:[^%]|^)(?:%%)*(%[a-z]))")

答案 1 :(得分:2)

您需要以不同的方式构建正则表达式:

>>> import re
>>> regex = re.compile(r"(?:[^%]|%%)*(%[a-z])")
>>> regex.findall("%d%%f%x%%%g")
['%d', '%x', '%g']

<强>说明:

(?:      # Start of a non-capturing group:
 [^%]    # Either match any character except %
|        # or
 %%      # match an "escaped" %.
)*       # Do this any number of times.
(        # Match and capture in group 1:
 %[a-z]  # % followed by a lowercase ASCII alphanumeric
)        # End of capturing group

答案 2 :(得分:2)

在我看来,您只希望捕获前面有偶数%x的每个部分%

如果是,则模式为"(?<!%)(?:%%)*(%[a-z])"