用awk或sed替换xml文件的部分

时间:2014-01-16 13:53:39

标签: xml regex bash sed awk

我想将<restApi></restApi>(包括restApi标记)之间的部分替换为另一个字符串:

...
  <restApi>
    <baseUrl>https://domain.com/nexus</baseUrl>
    <forceBaseUrl>true</forceBaseUrl>
    <uiTimeout>60000</uiTimeout>
  </restApi>
...

使用awk,我使用以下命令进行替换:

awk '/<restApi>/,/<\/restApi>/ {sub(/.*/,"<sometag>stuff</sometag>")}1' file.xml

问题是awk用替换字符串替换每一行,所以我得到了这个输出:

...
<sometag>stuff</sometag>
<sometag>stuff</sometag>
<sometag>stuff</sometag>
<sometag>stuff</sometag>
<sometag>stuff</sometag>
...
  • 在结果中只有一个"<sometag>stuff</sometag>"的awk命令中我缺少什么?
  • 如何使用sed代替?
  • 更换期间间距/标签丢失。我该如何保存它?

4 个答案:

答案 0 :(得分:4)

正如我在上面的评论中指出的那样,使用XML感知工具。

XSLT是一个,所以这里有一个简单的样式表,它取代<restApi>元素,同时保留其他所有元素,包括空格和制表符。

<!-- newRestApi.xsl -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="restApi">
    <sometag>stuff</sometag>
  </xsl:template>
</xsl:stylesheet>

xsltproc一起使用非常简单:

xsltproc newRestApi.xsl input.xml > output.html

答案 1 :(得分:3)

使用解析xml的方法不正确。您应该使用带解析器的语言。在这里,我将提供一个及其XML::Twig模块的示例:

假设有以下输入文件:

<root>
  <restApi>
    <baseUrl>https://domain.com/nexus</baseUrl>
    <forceBaseUrl>true</forceBaseUrl>
    <uiTimeout>60000</uiTimeout>
  </restApi>
  <t>data</t>
  <restApi>
    <baseUrl>https://domain.com/nexus</baseUrl>
    <forceBaseUrl>true</forceBaseUrl>
    <uiTimeout>60000</uiTimeout>
  </restApi>
</root>

关注perl脚本:

#!/usr/bin/env perl

use warnings;
use strict;
use XML::Twig;

XML::Twig->new(
    twig_handlers => {
        'restApi' => sub { 
            my $elem = XML::Twig::Elt->new('sometag', 'stuff');
            $elem->replace($_);
        },
    },
    pretty_print => 'indented',
)->parsefile(shift)->print;

像以下一样运行:

perl script.pl xmlfile

产量:

<root>
  <sometag>stuff</sometag>
  <t>data</t>
  <sometag>stuff</sometag>
</root>

答案 2 :(得分:3)

解决问题的单行纯awk 解决方案

awk  'BEGIN {A = 1};/<restApi>/{A=0; print "<sometag>stuff</sometag>"};/.*/ { if ( A == 1) print $0};/<\/restApi>/{A=1}; ' file.xml

如果你经常处理xml转换,你应该考虑使用xslt,正如其他人所说的那样

答案 3 :(得分:0)

如果你将awk输出传输到uniq,你可能会得到你想要的。