如果字符串在给定结构中出现两次(即像在 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')
关于python - 在正则表达式中查找具有相同字符串的两个匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47716948/