Shell脚本有条件地删除子xml标签

Déb*_*ora 3 xml sed awk shell-script

我有一个包含以下内容的 xml 文件。

<contracts>
    <clients>
        <client>
            <name>Nicol</name>
            <clientRef>123</clientRef>
        </client>
        <client>
            <name>Basil</name>
            <clientRef>8234</clientRef>
        </client>
    </clients>
    <entries>
        <entry>
            <regCode>BCG</regCode>
            <clientRef>63352</clientRef>
        </entry>
        <entry>
            <regCode>TYD</regCode>
            <clientRef>3242</clientRef>
        </entry>
    </entries>
</contracts>  
Run Code Online (Sandbox Code Playgroud)

xml 标签“clientRef”位于客户端和条目部分。但是,我只需要在客户端部分删除 clientRef 标记。

所需的输出是:

<contracts>
    <clients>
        <client>
            <name>Nicol</name>
        </client>
        <client>
            <name>Basil</name>
        </client>
    </clients>
    <entries>
        <entry>
            <regCode>BCG</regCode>
            <clientRef>63352</clientRef>
        </entry>
        <entry>
            <regCode>TYD</regCode>
            <clientRef>3242</clientRef>
        </entry>
    </entries>
</contracts>
Run Code Online (Sandbox Code Playgroud)

我是 shell 和 sed 命令的新手。如何使用 shell 脚本删除 clientRef 标记?

ter*_*don 13

尽管可能,但尝试使用基于正则表达式的工具解析 XML 或 HTML是一个非常非常糟糕的主意sed。这可以用于简单的案例,但很难做到正确,即使对于专家,甚至稍微复杂的案例也是如此。因此,请使用 XML 解析器,例如xmlstarlet(应该可以从操作系统的存储库中安装):

$ xmlstarlet ed -d '//client/clientRef' file.xml  
<?xml version="1.0"?>
<contracts>
  <clients>
    <client>
      <name>Nicol</name>
    </client>
    <client>
      <name>Basil</name>
    </client>
  </clients>
  <entries>
    <entry>
      <regCode>BCG</regCode>
      <clientRef>63352</clientRef>
    </entry>
    <entry>
      <regCode>TYD</regCode>
      <clientRef>3242</clientRef>
    </entry>
  </entries>
</contracts>
Run Code Online (Sandbox Code Playgroud)

ed手段“编辑该文件”并-d '//client/clientRef'表示“删除clientRef下的条目client”。


在这种特殊情况下,您还可以使用简单的文本解析工具,因此我将包含一个示例,但请不要对任何更复杂的内容执行此操作,并且请注意,即使对文本进行微小更改,也可能会中断输入数据:

$ awk '{ 
        if(/<clients>/){a=1}
        else if(/<\/clients>/){a=0} 
        if(/<clientRef>/ && a){ next}
       }1;' file.xml 
<contracts>
    <clients>
        <client>
            <name>Nicol</name>
        </client>
        <client>
            <name>Basil</name>
        </client>
    </clients>
    <entries>
        <entry>
            <regCode>BCG</regCode>
            <clientRef>63352</clientRef>
        </entry>
        <entry>
            <regCode>TYD</regCode>
            <clientRef>3242</clientRef>
        </entry>
    </entries>
</contracts>  
Run Code Online (Sandbox Code Playgroud)