我尝试捕获看起来像%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
,但它没有帮助。
答案 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])"