Skip to main content
 首页 » 编程设计

python之在正则表达式中查找具有相同字符串的两个匹配项

2025年05月04日38emanlee

如果字符串在给定结构中出现两次(即像在 XML 解析中一样),有没有办法在正则表达式中找到它? 这段代码显然不起作用,因为它找到了第一个标签,然后找到了最后一个结束标签:

re.findall(r'<(.+)>([\s\S]*)</(.+)>', s) 

那么有没有办法告诉正则表达式第三个匹配项应该与第一个相同?

完整代码:

import re 
 
s = '''<a1> 
    <a2> 
        1 
    </a2> 
    <b2> 
        52 
    </b2> 
    <c2> 
        <a3> 
            Abc 
        </a3> 
    </c2> 
</a1> 
<b1> 
    21 
</b1>''' 
 
matches = re.findall(r'<(.+)>([\s\S]*)</(.+)>', s) 
for match in matches: 
    print(match) 

结果应该是所有包含以下内容的标签:

    [('a1', '\n    <a2>\n        1\n    </a2>\n    <b2>\n        52\n    </b2>\n    <c2>\n        <a3>\n            Abc\n        </a3>\n    </c2>\n'), 
     ('a2', '\n        1\n    '), 
      ...] 

注意:我不是在寻找完整的xml解析包。这个问题具体是关于用正则表达式解决给定的问题。

请您参考如下方法:

您可以使用 backreferences和简单的递归:

>>> def m(s): 
...    matches = re.findall(r'<(.+)>([\s\S]*)</(\1)>', s) 
...    for k,s2,_ in matches: 
...        print (k,s2) 
...        m(s2) 
...  
>>> m(s) 
('a1', '\n    <a2>\n  ...[dropped]...      </a3>\n    </c2>\n') 
('a2', '\n        1\n    ') 
('b2', '\n        52\n    ') 
('c2', '\n        <a3>\n            Abc\n        </a3>\n    ') 
('a3', '\n            Abc\n        ') 
('b1', '\n    21\n') 

更多关于 backreferences from Microsoft Docs .

已编辑

为了获得额外的乐趣,使用发电机。感谢@mrCarnivore 关于删除 if s 的建议:

>>> def m(s): 
...    matches = re.findall(r'<(.+)>([\s\S]*)</(\1)>', s) 
...    for k,s2,_ in matches: 
...        yield (k,s2) 
...        yield from m(s2) 
...  
>>> for x in m(s): 
...    x 
...  
('a1', '\n    <a2>\ [....]     Abc\n        </a3>\n    </c2>\n') 
('a2', '\n        1\n    ') 
('b2', '\n        52\n    ') 
('c2', '\n        <a3>\n            Abc\n        </a3>\n    ') 
('a3', '\n            Abc\n        ') 
('b1', '\n    21\n')