我想替换我在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>
请帮我找出我在这里做错了什么?提前谢谢。
免责声明:正如人们在评论中提到的,这是一个危险的黑客。除非您确定输入的约束,否则它可能会产生意外的副作用。如果将包含AdmServer
Port
的行替换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>