sed命令替换第二次出现的xml标记

时间:2015-12-28 09:20:13

标签: regex xml bash sed

我有一个示例config.xml文件,如下所示:

<maven2-moduleset>
  <actions/>
   <jdk>JDK 6 Update 26</jdk>
  <publishers>
    <hudson.plugins.sonar.SonarPublisher plugin="sonar@2.1">
      <jdk>jdk1.8</jdk>
    </hudson.plugins.sonar.SonarPublisher>
  </publishers>
</maven2-moduleset>

我想更改<jdk></jdk>标记的第二次出现。所以我使用sed命令来做到这一点,如下所示:

sed -i "s/<jdk>\.*<\/jdk>/<jdk>jdk1.7.0_76<\/jdk>/2" config.xml

但该文件没有变化。我哪里错了?

注意:第二次出现的jdk标签可以包含任何jdk版本。我想将该标记中提到的任何值(版本)替换为此值=“jdk1.7.0_76”。 和, 我不能使用perl或xmlstarlet。

2 个答案:

答案 0 :(得分:3)

您的模式将在标签之间的任意数量的文字.上匹配文字,就是这样,这不是您想要的。此外,您要附加2,因为您希望匹配jdk标记对的第二次出现,但这只有在您的两对jdk标记出现在同一行时才有效。

如果你想匹配jdk标签之间某个时间段的任何内容,那么这将有效:

sed -i "s#<jdk>.*\..*</jdk>#<jdk>jdk1.7.0_76</jdk>#" config.xml

这只会替换第二个jdk标记对,因为第一个不包含.,它在上面的正则表达式中与\.匹配。

您还可以匹配任何不包含空格的内容:

sed -i "s#<jdk>[^ ]*</jdk>#<jdk>jdk1.7.0_76</jdk>#" config.xml

这是有效的,因为只有示例中的第二个实例缺少空格。

最后,您可以告诉sed仅替换jdk代码之间显示的hudson代码:

sed -i "/<hudson/,/<\/hudson/ s#<jdk>.*</jdk>#<jdk>jdk1.7.0_76</jdk>#" config.xml

我使用#代替/作为搜索分隔符,因为与/不同,它不会出现在正则表达式中。

答案 1 :(得分:0)

对于这种特定情况,您可以使用此sed命令:

sed -i "s/<jdk>jdk.*<\/jdk>/<jdk>jdk1.7.0_76<\/jdk>/g" config.xml

这应该用你自己的jdk版本替换jdk xml标签中的任何jdk[version]字符串。

但是,我建议你使用awk来做。 这应该可以解决问题:

awk '/<jdk>.*<\/jdk>/{c+=1}{if(c==2){sub("<jdk>.*</jdk>","<jdk>jdk.1.7.0_76</jdk>",$0)};print}' config.xml > config_new.xml

它查找<jdk></jdk> xml标签的第二次出现,然后替换该版本。