如何替换多个 XML 文件中的多个字段?

如何替换多个 XML 文件中的多个字段?

<filename>我有大约 4000 个 XML 文件,我需要替换和字段的值<path>。我需要动态替换这些字段。例如,images0001.xml应该images0001在两个字段内,images0002.xml应该images0002在两个字段内,等等。

我已经使用此命令按顺序重命名文件:

rename 's/.+/our $i; sprintf("images%04d.jpg", 1+$i++)/e' *

我还使用此命令删除了.jpg我尝试更改的两个字段中的扩展名:

sed -i 's/.jpg//g' Annotations/*

以下是 XML 文件内容的当前状态:

<annotation>
    <folder></folder>
    <filename>1608644703_2.rf.fa179c1e6c47d72d668ac3d83c7f79d1</filename>
    <path>1608644703_2.rf.fa179c1e6c47d72d668ac3d83c7f79d1</path>
    <source>
        <database>roboflow.ai</database>
    </source>
    <size>
        <width>416</width>
        <height>416</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>megot</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <occluded>0</occluded>
        <bndbox>
            <xmin>129</xmin>
            <xmax>292</xmax>
            <ymin>145</ymin>
            <ymax>351</ymax>
        </bndbox>
    </object>
</annotation>

以下是我需要更改文件的方式:

<annotation>
    <folder></folder>
    <filename>images0001</filename>
    <path>images0001</path>
    <source>
        <database>roboflow.ai</database>
    </source>
    <size>
        <width>416</width>
        <height>416</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>megot</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <occluded>0</occluded>
        <bndbox>
            <xmin>129</xmin>
            <xmax>292</xmax>
            <ymin>145</ymin>
            <ymax>351</ymax>
        </bndbox>
    </object>
</annotation>

我正在寻找一种在命令行中执行此操作的方法,但搜索了一段时间后仍找不到解决方案!

任何帮助都将不胜感激。提前致谢!

答案1

您需要一个 XML 工具(喜欢xmlstarlet) ... 所以:

sudo snap install xmlstarlet

在一个循环中...所以:

for f in *.xml
    do
    xml ed -L -u "(//annotation/filename)" -v "${f/.xml/}" -u "(//annotation/path)" -v "${f/.xml/}" "$f"
    done

答案2

一种方法是sed方法是运行以下命令:

for f in *.xml; do sed "s|\(<filename>\).*\(</filename>\)|\1${f%.*}\2|; s|\(<path>\).*\(</path>\)|\1${f%.*}\2|" "$f"; done
  • for f in *.xml; do ... ; done基本 for 循环查找.xml当前目录中的文件。找到的每个文件都存储在f变量中。

  • sed "s|\(<filename>\).*\(</filename>\)|\1${f%.*}\2|; s|\(<path>\).*\(</path>\)|\1${f%.*}\2|" "$f"是针对找到的每个文件运行的命令。该命令执行两个类似的替换,一个针对字段<filename>,另一个针对<path>字段:

    • s|\(<filename>\).*\(</filename>\)|\1${f%.*}\2|\(<filename>\).*\(</filename>\)匹配使用文本正则表达式(表示匹配和.*之间的任意字符)。和不匹配,但用于<filename></filename>\(\)捕获<path>和文本</filename>,然后用作替换。然后文本是被第一个捕获替换 \1<filename>), 这不带扩展名的文件名 ${f%.*},第二个捕获是\2</filename>)。

    • 类似地path,使用它代替filename

通过在文件的复制部分中使用上述命令确保其按预期工作后,-i立即添加标志sed以更改文件。

相关内容