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

时间:2022-09-12 16:52:55

I'd like to replace the section below between <restApi> and </restApi> (including restApi tags) with another string:

我想用另一个字符串替换下面 (包括restApi标签)之间的部分:

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

Using awk, I use the following command to do the replacement :

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

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

The problem is that awk replaces each line with the replacement string so I'm getting this output:

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

...
<sometag>stuff</sometag>
<sometag>stuff</sometag>
<sometag>stuff</sometag>
<sometag>stuff</sometag>
<sometag>stuff</sometag>
...
  • What am I missing in the awk command to have only one "<sometag>stuff</sometag>" in the result?
  • awk命令中只缺少一个“ stuff ”,这是什么意思?
  • How do I do it with sed instead?
  • 我怎么用sed代替它呢?
  • Spacing/tabs get lost during replacement. How can I preserve it?
  • 间隔/标签在替换过程中丢失。我如何保存它?

4 个解决方案

#1


3  

A single line pure awk solution that solves your problem

单行纯awk解决方案,解决您的问题。

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

If you're dealing often with xml transforms you should consider using xslt, as others say

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

#2


4  

As pointed out in my comment above, use an XML aware tool.

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

XSLT is one, so here is a simple stylesheet that replaces <restApi> elements while leaving everything else alone, including spaces and tabs.

XSLT就是其中之一,因此这里有一个简单的样式表,它替换了 元素,而不保留其他所有元素,包括空格和制表符。

<!-- 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>

Use with xsltproc is dead-simple:

与xsltproc一起使用非常简单:

xsltproc newRestApi.xsl input.xml > output.html

#3


3  

It's an incorrect approach to parse xml with or . You should use a language with a parser. Here I will provide an example with and its XML::Twig module:

使用sed或awk解析xml是一种错误的方法。您应该使用带有解析器的语言。在这里,我将提供一个perl及其XML::Twig模块的示例:

Assuming following input file:

假设输入文件:

<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>

And following perl script:

和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;

Run it like:

运行该程序:

perl script.pl xmlfile

That yields:

收益率:

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

#4


0  

If you pipe your awk output into uniq, you probably get what you want.

如果您将awk输出导入uniq,您可能会得到您想要的结果。

#1


3  

A single line pure awk solution that solves your problem

单行纯awk解决方案,解决您的问题。

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

If you're dealing often with xml transforms you should consider using xslt, as others say

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

#2


4  

As pointed out in my comment above, use an XML aware tool.

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

XSLT is one, so here is a simple stylesheet that replaces <restApi> elements while leaving everything else alone, including spaces and tabs.

XSLT就是其中之一,因此这里有一个简单的样式表,它替换了 元素,而不保留其他所有元素,包括空格和制表符。

<!-- 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>

Use with xsltproc is dead-simple:

与xsltproc一起使用非常简单:

xsltproc newRestApi.xsl input.xml > output.html

#3


3  

It's an incorrect approach to parse xml with or . You should use a language with a parser. Here I will provide an example with and its XML::Twig module:

使用sed或awk解析xml是一种错误的方法。您应该使用带有解析器的语言。在这里,我将提供一个perl及其XML::Twig模块的示例:

Assuming following input file:

假设输入文件:

<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>

And following perl script:

和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;

Run it like:

运行该程序:

perl script.pl xmlfile

That yields:

收益率:

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

#4


0  

If you pipe your awk output into uniq, you probably get what you want.

如果您将awk输出导入uniq,您可能会得到您想要的结果。