Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在正则表达式中查找具有相同字符串的两个匹配项_Python_Regex_Python 3.x - Fatal编程技术网

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

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

如果字符串在给定结构中出现两次(如XML解析),在正则表达式中是否有方法查找该字符串? 此代码显然不起作用,因为它会找到第一个标记,然后是最后一个结束标记:

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@马提尼:好的