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

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

我有一个包含以下内容的 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>  

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>

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

答案1

虽然有可能,但它是一个非常非常糟糕的主意尝试使用sed基于正则表达式的工具来解析 XML 或 HTML。这可以适用于简单的情况,但很难做到正确,即使对于专家来说,对于稍微复杂的情况。因此,请使用 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>

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

答案2

使用xqXML 解析器(部分yq),它是一个包装器jq(因此它正在执行 XML/JSON 转码):

$ xq -x 'del(.contracts.clients.client[].clientRef)' 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>

相关内容