20

快速总结:我需要创建一个 Bash 脚本来每周自动更改节点内的文本。脚本将匹配节点并替换其中的文本(如果可能的话)?我该怎么做?

长总结: 我托管了一个包含商店的 Minecraft 服务器,每个商店在 /ShowcaseStandalone/ffs-storage/ 目录中都有自己的 .xml 文件。每个星期天我的服务器都会重新启动并在终端中执行几个命令来重置一些东西。我想要改变的一件事是其中一家商店。我想更改节点 <itemstack> 中的文本和节点 <price> 中的文本。我只是想从不同文件夹中的 .txt 文件中获取文本,并将其插入该节点。问题是,节点中的文本每周都会更改。有没有办法使用 bash 替换两个节点内的特定行或文本?

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

4

3 回答 3

19

您可以使用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
于 2012-11-13T22:46:58.913 回答
13

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指第二个括号组,在这种情况下是结束标记。

于 2012-11-13T23:24:47.403 回答
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>
于 2016-09-21T20:42:29.773 回答