快速摘要: 我需要创建一个 Bash 脚本来每周自动更改节点内的文本。该脚本将匹配节点并替换其中的文本(如果可能的话)?我该怎么做?
长总结:
我托管一个 Minecraft 服务器,其中有商店,每个商店在 /ShowcaseStandalone/ffs-storage/ 目录中都有自己的 .xml 文件。每个星期日我的服务器都会重新启动并在终端中执行多个命令以重置一些内容。我试图改变的一件事是其中一间商店。我想更改节点
XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<scs-shop usid="cac8480951254352116d5255e795006252d404d9" version="2" type="storage">
<enchantments type="string"/>
<owner type="string">Chadward27</owner>
<world type="string">Frisnuk</world>
<itemStack type="string">329:0</itemStack>
<activity type="string">BUY</activity>
<price type="double">55.0</price>
<locX type="double">487.5</locX>
<locY type="double">179.0</locY>
<locZ type="double">-1084.5</locZ>
<amount type="integer">0</amount>
<maxAmount type="integer">0</maxAmount>
<isUnlimited type="boolean">true</isUnlimited>
<nbt-storage usid="23dffac5fb2ea7cfdcf0740159e881026fde4fa4" version="2" type="storage"/>
</scs-shop>
操作系统:Linux Ubuntu 12.04
xmlstarlet
在 XML
中编辑 shell
文件,如下所示:
xmlstarlet edit -L -u "/scs-shop/price[@type='double']" -v '99.66' file.xml
注意
"/scs-shop/price[@type='double']"
是一个 Xpath 表达式xmlstarlet ed --help
XML 方式很酷,但是如果您需要使用普通的 bash 工具,您可以使用 sed 修改一行。例如:
PRICE=123
sed -i "s/\(<price.*>\)[^<>]*\(<\/price.*\)/\1$PRICE\2/" $XML_FILE_TO_MODIFY
这会将价格替换为 123。
sed 命令看起来令人畏惧,所以让我来分解一下:
\(<price.*>\)[^<>]*\(<\/price.*\)
是要匹配的模式。 \(
... \)
是用于分组的括号。 <price.*>
与开盘价相符。 [^<>]*
匹配除尖括号之外的任何内容,在这种情况下将匹配价格标签的内容。 <\/price.*
与价格标签的末尾相符。正斜杠是 sed 中的分隔符,所以我用反斜杠转义它。
\1$PRICE\2
是替换匹配文本的文本。 \1
指第一个匹配的括号组,即开盘价标签。 $PRICE
是包含所需价格的变量。 \2
指第二个括号组,在本例中为结束标记。
我没有幸拥有 xmlstarlet。 我通过简单地进行内联替换找到了一个解决方案;
模板参数.xml
<ns:Parameter>
<ns:Name required="true">##-ParamName-##</ns:Name>
<ns:Value>
<ns:Text>##-ParamValue-##</ns:Text>
</ns:Value>
</ns:Parameter>
片段
tokenName="foo"
tokenValue="bar"
#Replace placeholders in parameter template element
myParamElement=$(cat template-parameter.xml)
myParamElement=${myParamElement//##-ParamName-##/$tokenName}
myParamElement=${myParamElement//##-ParamValue-##/$tokenValue}
结果
<ns:Parameter>
<ns:Name required="true">foo</ns:Name>
<ns:Value>
<ns:Text>bar</ns:Text>
</ns:Value>
</ns:Parameter>