非贪婪 XML(Python 正则表达式)中的多个匹配项

Multiple matches in non-greedy XML (Python regex)

我知道这个话题被问了很多,但我找不到问题的答案:

在附图中有许多不同的缓冲区,我希望只匹配名称中包含 "Lut" 的缓冲区(注意图像中的字符串中有 2 个匹配项)。我遇到的问题是匹配项还包含我想要的缓冲区之前的缓冲区。

我是正则表达式的新手,仍在努力学习,所以任何解释都将不胜感激。

谢谢! :)

附上绳子是为了让您感到舒适(如果需要):

<?xml version="1.0" encoding="utf-8"?>
<pimp xmlns:dt="urn:schemas-microsoft-com:datatypes">
    <dllPath>C:\ReplayCode\Apps\Pimp</dllPath>
    <buffers>   
    <buffer name="InputMask">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>
    <buffer name="MaskErode">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>
    <buffer name="BlablaLutBla">
            <width>256</width>
            <height>256</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>
    <buffer name="MaskClose">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>
    <buffer name="InputVis">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>3</channels>
            <type>IMG</type>
    </buffer>   
        <buffer name="AddMaskEdge">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>
    <buffer name="EdgeVis">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>3</channels>
            <type>IMG</type>
    </buffer>       
        <buffer name="GrayEdge">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>
    <buffer name="EdgeMaskMulThreshold">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>
    <buffer name="MaskMulEdge">
            <width>5120</width>
            <height>3072</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>   
    </buffers>  

我试过的正则表达式是这样的:

<buffer name=".*?Lut.*?">.*?<\/buffer>

我预计有 2 场比赛:

<buffer name="BlablaLutBla">
            <width>256</width>
            <height>256</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>

<buffer name="2ndLutBlabla">
            <width>256</width>
            <height>256</height>
            <data>UCHAR</data>
            <channels>1</channels>
            <type>IMG</type>
    </buffer>

您可以使用 BeautifulSoup 来解析您的标签。

import re
from bs4 import BeautifulSoup

input_xml = ''' some xml '''
soup = BeautifulSoup(input_xml, "lxml-xml")
print soup.find_all('buffer', attrs={"name": re.compile('Lut')})

如果您还没有安装这个:

pip install beautifulsoup4
pip install lxml

您可能想在 python 中使用 xml 解析,这很简单:

import xml.etree.ElementTree as ET
tree = ET.parse(xml)
for buffer in tree.findall("buffers/buffer"): 
    if "Lut" in buffer.get("name"):
        # do your stuff
        pass
<buffer name="[^"]*Lut[^"]*">.*?<\/buffer>

Demo

在您的正则表达式 <buffer name=".*?Lut 中,它将匹配第一个 <buffer 到第一个 Lut。(non-greedy worked.If greedy,it will match the last Lut)

由于您需要操作 XML 文档中的数据,因此请使用 XML 解析器。 上面的答案已经显示了如何实例化 XML 树,但没有详述结构修改。

顺便说一句,如果您从字符串实例化 XML,请使用 ET.fromstring

import xml.etree.ElementTree as ET
...
xml = "<<YOUR XML STRING>>" 
root = ET.fromstring(xml)

否则,从文件读取时:

tree = ET.parse('file.xml')
root = tree.getroot()

然后,您可以使用以下替换(如果需要,您实际上可以使用正则表达式,因为在这里您已经必须处理纯文本数据):

for buffer in root.findall("buffers/buffer"): 
    if "Lut" in buffer.get("name"):
        buffer.find('width').text = "100"    # Set inner text of buffer child named 'width'
        buffer[1].text = "125"               # Set the 2nd child inner text
        buffer.set('type', 'MY_TYPE');       # Add an attribute to buffer

您可以使用 .dump():

打印更新后的 XML
print ET.dump(root)                          # Print updated XML

或者将更新的 DOM 写入文件(如果您正在使用文件):

tree.write('output.xml')

参见 IDEONE demo 显示对 XML 字符串的修改。