Python正则表达式中的可选贪婪组

6 投票
5 回答
2669 浏览
提问于 2025-04-16 12:24

我正在尝试写一个正则表达式,用来匹配一个字符串,这个字符串可能包含也可能不包含两个标签。我需要这个表达式能根据标签是否存在,返回字符串中的所有五个部分,但当我把标签设为可选时,通配符的部分似乎会把它们都吞掉:

输入可能是:

text{a}more{b}words  
{a}text{b}test  
text  
text{b}text  
text{b}  
text{a}text 

等等。唯一可以保证的是,<a> 标签总是在 <b> 标签之前,如果它们存在的话。

我现在的表达式看起来是这样的:

^(.*?)(\{a\})?(.*?)(\{b\})?(.*?)$

不幸的是,这样做会把所有文本都放进最后一个组里,无论标签是否存在。有没有办法让它们贪婪一些,同时又保持可选呢?可惜 re.findall 似乎也没有帮助。

任何帮助都会非常感谢! :)

5 个回答

0

不太确定这是否能得到你想要的结果,不过:

import re

inputs = ['text{a}more{b}words',
'{a}text{b}test',
'text',
'text{b}text',
'text{b}',
'text{a}text']

pattern = re.compile(r'^([^{]*)(\{a\})?([^{]*)(\{b\})?([^{]*)$')

for inpt in inputs:
    match = pattern.match(inpt)
    if match:
        print match.groups()
0

我找到了一种解决办法,虽然看起来不太好看,但似乎有效:

^((?P<b1>.*)(?P<o1>\{start\})(?P<m1>.*)(?P<c1>\{end\})(?P<e1>.*))|((?P<b2>.*)(?P<c2>\{end\})(?P<e2>.*))|((?P<b3>.*)(?P<o3>\{start\})(?P<e3>.*))$
4

试试下面这个正则表达式:^(.*(?={a})|.*?)({a})?(.*(?={b})|.*)({b})?(.*?)$

import re

inputs = ['{a}text{b}test', 'text', 'text{b}text', 'text{b}', 'text{a}text']
p = re.compile(r"^(.*(?={a})|.*?)({a})?(.*(?={b})|.*)({b})?(.*?)$")
for input in inputs:
    print p.match(input).groups()

输出结果:

('', '{a}', 'text', '{b}', 'test')
('', None, 'text', None, '')
('', None, 'text', '{b}', 'text')
('', None, 'text', '{b}', '')
('text', '{a}', 'text', None, '')

撰写回答