用bash替换xml中的标签

时间:2015-07-24 22:51:51

标签: regex xml linux bash sed

我有一个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'命令。

当我尝试时:

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

我明白了:

  

未终止的地址正则表达式

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

2 个答案:

答案 0 :(得分:5)

Don't use text-manipulation tools such as awk or sed to work with XML if you can at all avoid it.虽然这个特定的子集可能非常简单,只是为了使方法可行,但掌握正确的工具可以避免以后的麻烦(如果文件格式扩展;如果有人在前面添加评论;等等)。

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

答案 1 :(得分:0)

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

它因为匹配和替换变量包含/

而中断