Bash
更改標籤中的文本,但只有標籤包含在某個 XML 塊中
使用 Git Bash,我試圖有條件地替換數百個文件中 yrot 標籤中的內容,但前提是它屬於與 wheel 相關的元件名稱標籤。
// YES, change <part name="D_wheel1" seqNumber="1" > <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> // YES, change <part name="D_wheel2" seqNumber="1" > <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> // NO, don't change <part name="door" seqNumber="1" > <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> // Example Line Change // From: <yrot min="0.000000" max="0.000000" cur="0.000000" /> // To: <yrot min="INF" max="INF"/>
這甚至可以使用 awk 之類的嗎?還是我需要使用某種特殊的 XML 解析器?
編輯:要清楚,大約有十幾個標籤屬於 ,其中一個是 . 只出現在標籤內。如果名稱包含“wheel”,我只想替換該行。本身是嵌套的。
對於那些聲稱我需要 XML 解析器的人,如果滿足條件(yrot 標籤在輪子中),為什麼不只是簡單的文本查找/替換工作?檢查有那麼難嗎?
使用 python 的 ElementTree 標準庫:
#! /usr/bin/env python import sys import xml.etree.ElementTree as ET def do_one(file_name): tree = ET.parse(file_name) for part in tree.findall("part"): if not 'wheel' in part.attrib['name']: continue for yrot in part.findall('yrot'): names = [] for x in yrot.attrib: names.append(x) for x in names: del yrot.attrib[x] yrot.attrib['min'] = 'INF' yrot.attrib['max'] = 'INF' tree.write(file_name) for file_name in sys.argv[1:]: do_one(file_name)
這會將命令行上傳遞的所有文件解析到腳本:
python convert_xml.py *.xml
將您的 XML 提供
data.xml
為:$ cat data.xml <?xml version="1.0" encoding="UTF-8"?> <root> <part name="D_wheel1" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> <part name="D_wheel2" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> <part name="door" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000" /> </part> </root>
xmlstarlet
與XPath一起使用:$ xmlstarlet ed \ --var target '//part[contains(@name, "wheel")]/yrot' \ -u '$target/@*[name()="min" or name()="max"]' -v 'INF' \ -d '$target/@cur' data.xml <?xml version="1.0" encoding="UTF-8"?> <root> <part name="D_wheel1" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="D_wheel2" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="door" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000"/> </part> </root>
或使用XSLT的經典方法:和
xsltproc
或xmlstarlet
$ cat data.xsl <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="*[contains(@name, 'wheel')]/yrot"> <xsl:copy> <xsl:attribute name="min">INF</xsl:attribute> <xsl:attribute name="max">INF</xsl:attribute> </xsl:copy> </xsl:template> </xsl:stylesheet> $ xsltproc data.xsl data.xml #or: xmlstarlet tr data.xsl data.xml <?xml version="1.0" encoding="UTF-8"?> <root> <part name="D_wheel1" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="D_wheel2" seqNumber="1"> <yrot min="INF" max="INF"/> </part> <part name="door" seqNumber="1"> <yrot min="0.000000" max="0.000000" cur="0.000000"/> </part> </root>