【问题标题】:Replacing tags in xml in bash在bash中替换xml中的标签
【发布时间】:2015-10-15 17:47:53
【问题描述】:

我有一个格式如下的 xml 文件:

<list>
    <version>1.5</version>
    <version>1.4</version>
    <version>1.3</version>
    <version>1.2</version>
</list>

我的想法是我总是用新版本更新第一个版本标签。当我这样做时,我会替换后续的标签。

例如,当我将 1.6 版本更新为第一个标签(我知道该怎么做)时,以下标签将是:

<list>
    <version>1.6</version>
    <version>1.5</version>
    <version>1.4</version>
    <version>1.3</version>  
</list>

我尝试了两种选择。

第一个选项: 我的首选选项是搜索 xml 文件并将版本标签 i+1 替换为版本标签 i。比如:

sed -E '2,/<version>.*<\/version>/s#<version>(.*)</c>#<version>\1</version>#' file.xml

我在哪里搜索版本的第二个实例并将其替换为版本的第一个实例(当前不工作)。

第二个选项: 我的第二个选择是将版本标签存储在变量中,例如:

version=$(grep -oPm1 "(?<=version>)[^<]+" file.xml)
version2=$(grep -oPm2 "(?<=version>)[^<]+" file.xml)

然后用版本1替换版本2并进行替换:

sed -i "s/${version2}/${version}/g" file.xml

但是,此选项给出:

sed: -e expression #1, char 9: unterminated 's' command.

当我尝试时:

sed -i "/$version2/s/${version2}/${version}/g" file.xml

我明白了:

未终止的地址正则表达式

显然,任一选项的想法都是将代码放入一个循环中,以便我可以运行它 i 次。但是,我被卡住了,我尝试过的两个选项都不起作用。

【问题讨论】:

    标签: regex xml linux bash sed


    【解决方案1】:

    Don't use text-manipulation tools such as awk or sed to work with XML if you can at all avoid it. 虽然这个特定的子集可能非常简单,以使该方法可行,但手头有合适的工具将避免以后的麻烦(如果文件格式得到扩展;如果有人在前面添加 cmets 等)。

    new_version=1.6
    xmlstarlet ed \
      -d '/list/version[last()]' \
      -i '/list/version[1]' -t elem -n version -v "$new_version" \
      <old.xml >new.xml
    
    • -d '/list/version[last()]' 删除列表中的最后一个 version 条目。
    • -i '/list/version[1]' -t elem -n version -v 1.6 引入了一个名为 version 的新元素,其值为 1.6,处于当前第一个版本所占据的位置。

    【讨论】:

    • 感谢您的回答。我可以尝试使用 xmlstarlet,但你将如何在 centos 机器上安装它? yum install xmlstarlet 不起作用。安装好后,我会试试你的代码。
    • xmlstarlet 在 EPEL 存储库中。有关安装说明,请参阅fedoraproject.org/wiki/EPEL
    • 工作就像一个魅力!谢谢:)
    【解决方案2】:

    使用!或 # 作为 sed 中的分隔符,而不是 /。

    它会中断,因为您的匹配和替换变量包含 /

    【讨论】:

    • 我更喜欢@! 对于具有历史扩展的 shell 来说是有意义的,并且许多语法高亮引擎将 # 视为注释字符,即使在不能这样使用的位置也是如此。
    猜你喜欢
    • 2013-07-03
    • 2012-09-25
    • 2012-09-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    相关资源
    最近更新 更多