使用 sed 使用变量替换 xml 中的值



我想替换我在xml文件中使用"grep"找到的值。值在变量中传递,我为此使用"sed"。

$ echo $AdmServerPort
9595
$ grep -A 8 AdmServer PoolServer.xml | grep Port
<Argument Name="Port" Value="9090"/>
$ grep -A 8 AdmServer PoolServer.xml | grep Port | xargs sed "s/9090/$AdmServerPort/g"
sed: can't read <Argument: No such file or directory
sed: can't read Name=Port: No such file or directory
: No such file or directory>

请帮我找出我在这里做错了什么?提前谢谢。

免责声明:正如人们在评论中提到的,这是一个危险的黑客。除非您确定输入的约束,否则它可能会产生意外的副作用。如果将包含AdmServerPort的行替换9090正是您想要执行的操作,那么可以执行以下操作:

sed "/AdmServer/,+8 {/Port/s/9090/$AdmServerPort/}" PoolServer.xml

如果要就地修改文件,请使用-i标志。

示例输入:

<AdmServer>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Port" Value="9090"/>
</AdmServer>

示例输出:

<AdmServer>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9595"/>
<Argument Name="Port" Value="9595"/>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9595"/>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9595"/>
<Argument Name="Port" Value="9595"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Foo" Value="9090"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Port" Value="9090"/>
</AdmServer>

libxml 解决方案:您可以将新的Port属性值作为参数传递给 xsltproc,以便在标识转换样式表中使用:

xsltproc --stringparam new_port 9595 PoolServer.xsl PoolServer.xml

PoolServer.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- define $new_port as a parameter received from the shell -->
<xsl:param name="new_port"/>
<!-- match AdmServer/Argument 'Value' attributes
whose sibling 'Name' attributes are 'Port' -->
<xsl:template match="AdmServer/Argument/@Value[../@Name = 'Port']">
<xsl:attribute name="Value">
<xsl:value-of select="$new_port"/>
</xsl:attribute>
</xsl:template>
<!-- recursively copy the rest of the xml document -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

输入池服务器.xml:

<AdmServer>
<Argument Name="Sample1" Value="1234"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Sample2" Value="1234"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Port" Value="9090"/>
</AdmServer>

输出:

<?xml version="1.0"?>
<AdmServer>
<Argument Name="Sample1" Value="1234"/>
<Argument Name="Port" Value="9595"/>
<Argument Name="Sample2" Value="1234"/>
<Argument Name="Port" Value="9595"/>
<Argument Name="Port" Value="9595"/>
</AdmServer>

yq 可用于 XML 处理。

输入

<AdmServer>
<Argument Name="Sample1" Value="1234"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Sample2" Value="1234"/>
<Argument Name="Port" Value="9090"/>
<Argument Name="Port" Value="9090"/>
</AdmServer>

PORT=9595 yq --input-format xml --output-format xml e '(.. | (select(type == "!!map") | select(."+Name" == "Port") | ."+Value")) |= env(PORT)' "$INPUT"

  • 注意:对于版本>= 4.30,将+Value替换为+@Value

输出

<AdmServer>
<Argument Name="Sample1" Value="1234"></Argument>
<Argument Name="Port" Value="9595"></Argument>
<Argument Name="Sample2" Value="1234"></Argument>
<Argument Name="Port" Value="9595"></Argument>
<Argument Name="Port" Value="9595"></Argument>
</AdmServer>

最新更新