Python 在正则表达式中查找具有相同字符串的两个匹配项
如果字符串在给定结构中出现两次(如XML解析),在正则表达式中是否有方法查找该字符串? 此代码显然不起作用,因为它会找到第一个标记,然后是最后一个结束标记:Python 在正则表达式中查找具有相同字符串的两个匹配项,python,regex,python-3.x,Python,Regex,Python 3.x,如果字符串在给定结构中出现两次(如XML解析),在正则表达式中是否有方法查找该字符串? 此代码显然不起作用,因为它会找到第一个标记,然后是最后一个结束标记: re.findall(r'<(.+)>([\s\S]*)</(.+)>', s) re.findall(r'([\s\s]*),s) 那么有没有办法告诉regex第三场比赛应该和第一场比赛一样 完整代码: import re s = '''<a1> <a2> 1
re.findall(r'<(.+)>([\s\S]*)</(.+)>', s)
re.findall(r'([\s\s]*),s)
那么有没有办法告诉regex第三场比赛应该和第一场比赛一样
完整代码:
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)
重新导入
s='''
1.
52
Abc
21
'''
matches=re.findall(r'([\s\s]*),s)
对于匹配中的匹配:
打印(匹配)
结果应为包含以下内容的所有标签:
[('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 '),
...]
[('a1','\n\n 1\n\n\n 52\n\n\n\n Abc\n\n\n'),
('a2','\n 1\n'),
...]
注意:我不是在寻找一个完整的xml解析包。这个问题具体是关于用正则表达式解决给定问题。您可以使用简单的递归:
>>> 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')
您可以使用和简单递归:
>>> 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')
我不会这么做,因为递归结构很难用正则表达式解析。Python的
re
模块不支持此功能。另一个regex
模块会执行此操作。然而,我不会这么做
A只能让你走到这一步:
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]*)</\1>', s) # mind the \1
for match in matches:
print(match)
重新导入
s='''
1.
52
Abc
21
'''
matches=re.findall(r'([\s\s]*),s)#注意\1
对于匹配中的匹配:
打印(匹配)
它将为您提供两个匹配项:1。代码>和代码>
现在假设您的一些标记具有属性。如果一个标记可以跨越多行怎么办?那些自动关闭的标签呢?意外空间呢
html/xml解析器可以处理所有这些问题。我不会这样做,因为递归结构很难用正则表达式解析。Python的re
模块不支持此功能。另一个regex
模块会执行此操作。然而,我不会这么做
A只能让你走到这一步:
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]*)</\1>', s) # mind the \1
for match in matches:
print(match)
重新导入
s='''
1.
52
Abc
21
'''
matches=re.findall(r'([\s\s]*),s)#注意\1
对于匹配中的匹配:
打印(匹配)
它将为您提供两个匹配项:1。代码>和代码>
现在假设您的一些标记具有属性。如果一个标记可以跨越多行怎么办?那些自动关闭的标签呢?意外空间呢
html/xml解析器可以处理所有这些问题。使用danihp在回答中给我的帮助,并遵循注释中给出的提示,我能够创建一个轻量级xml解析器,返回xml的dict结构:
import re
def xml_loads(xml_text):
matches = re.findall(r'<([^<>]+)>([\s\S]*)</(\1)>', xml_text)
if not matches:
return xml_text.strip()
d = {}
for k, s2, _ in matches:
d[k] = xml_loads(s2)
return d
s = '''<a1>
<a2>
1
</a2>
<b2>
52
</b2>
<c2>
<a3>
Abc
</a3>
</c2>
</a1>
<b1>
21
</b1>'''
d = xml_loads(s)
print(d)
重新导入
def xml_加载(xml_文本):
matches=re.findall(r'([\s\s]*),xml\u text)
如果不匹配:
返回xml_text.strip()
d={}
对于k,s2,u在匹配中:
d[k]=xml_加载(s2)
返回d
s='''
1.
52
Abc
21
'''
d=xml_加载
印刷品(d)
使用danihp在回答中给出的帮助,并遵循注释中给出的提示,我能够创建一个轻量级xml解析器,返回xml的dict结构:
import re
def xml_loads(xml_text):
matches = re.findall(r'<([^<>]+)>([\s\S]*)</(\1)>', xml_text)
if not matches:
return xml_text.strip()
d = {}
for k, s2, _ in matches:
d[k] = xml_loads(s2)
return d
s = '''<a1>
<a2>
1
</a2>
<b2>
52
</b2>
<c2>
<a3>
Abc
</a3>
</c2>
</a1>
<b1>
21
</b1>'''
d = xml_loads(s)
print(d)
重新导入
def xml_加载(xml_文本):
matches=re.findall(r'([\s\s]*),xml\u text)
如果不匹配:
返回xml_text.strip()
d={}
对于k,s2,u在匹配中:
d[k]=xml_加载(s2)
返回d
s='''
1.
52
Abc
21
'''
d=xml_加载
印刷品(d)
谢谢,这比我希望的容易多了!但是,为什么要检查for循环中s
的值?您是想检查s2
?反向参考是正确的方法。(\1)
被称为反向引用,它匹配括号中第一个捕获的匹配标记。您需要它,因为您希望只与匹配以获得适当的内容。简言之,你是在“指回”之前的比赛,这正是你在这里需要的。您还需要递归,因为匹配往往是“饥饿”的。当您匹配第一个“a1”标记时,它会消耗整个标记。因此,如果没有递归,您只能找到'a1'和'b1'。Gary02127:这不是我的问题。我已经理解了反向引用的概念。我没有得到的是为什么函数中有一行if s:
。在那个位置上,我觉得毫无意义……我们的帖子重叠了。@Gary02127:哦,好的。所以你只是想强调答案是解决这个问题的最好方法?谢谢,这比我希望的要容易!但是,为什么要检查for循环中s
的值?您是想检查s2
?反向参考是正确的方法。(\1)
被称为反向引用,它匹配括号中第一个捕获的匹配标记。您需要它,因为您希望只与匹配以获得适当的内容。简言之,你是在“指回”之前的比赛,这正是你在这里需要的。您还需要递归,因为匹配往往是“饥饿”的。当您匹配第一个“a1”标记时,它会消耗整个标记。因此,如果没有递归,您只能找到'a1'和'b1'。Gary02127:这不是我的问题。我已经理解了反向引用的概念。我没有得到的是为什么函数中有一行if s:
。在那个位置上,我觉得毫无意义……我们的帖子重叠了。@Gary02127:哦,好的。所以你只是想强调答案是解决这个问题的最好方法?我个人会使用一个类似这样的标记mactcher,这样你就不会用“.”或“*”通配符在标记边界上过度运行grep和slurp@马提尼:好的