移除所有节点!=标签值

移除所有节点!=标签值

我知道 xml 解析器是这里的理想方式,但没有一个可用或能够添加到我的环境中。

让我们采用遵循以下结构的 XML:

<CONTAINER>
  <FOLDER NAME="I_RS_INT">
  </FOLDER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
  <FOLDER NAME="I_RS_TRN">
  </FOLDER>
</CONTAINER>

在 bash 脚本中,我希望删除匹配的所有节点<FOLDER NAME=*RS*删除其中的所有节点<FOLDER NAME != $var_folder

非常感谢任何帮助!

答案1

这应该可以做到:

cat /tmp/xml  | sed -e '/<FOLDER NAME=.*RS.*>/ { N; d; }'

对于与两个/字符之间的模式匹配的每一行,都会执行 {} 中的代码。 N 也将下一行放入模式空间,然后 d 在继续下一行之前删除整个内容。这适用于任何 POSIX 兼容的sed.

尝试以下操作删除<FOLDER NAME=.*RS.*>和之间的每一行</FOLDER.>

 awk '/<FOLDER NAME=.*RS.*>/,/<\/FOLDER>/ {next} {print}' xmlfile

next命令停止当前匹配的处理。接下来是一个简单的print.

答案2

您应该使用 XML 解析器来完成此操作。例如,使用XML小星在命令行上:

$ xmlstarlet ed -d '/CONTAINER/FOLDER[contains(@NAME, "RS")]' data.xml
<?xml version="1.0"?>
<CONTAINER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
</CONTAINER>

或者,

$ var="I_R_INR"
$ xmlstarlet ed -d "/CONTAINER/FOLDER[@NAME != '$var']" data.xml
<?xml version="1.0"?>
<CONTAINER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
</CONTAINER>

请注意,这两个示例并不等效,因为第一个示例执行子字符串匹配,而第二个示例执行精确匹配。


有了xq包装纸jq

$ xq -x --arg substring "RS" 'del(.CONTAINER.FOLDER[] | select(."@NAME" | contains($substring)))' file.xml
<CONTAINER>
  <FOLDER NAME="I_R_INR"></FOLDER>
</CONTAINER>
$ xq -x --arg name "I_R_INR" 'del(.CONTAINER.FOLDER[] | select(."@NAME" != $name))' file.xml
<CONTAINER>
  <FOLDER NAME="I_R_INR"></FOLDER>
</CONTAINER>

答案3

好吧,说真的 - 用正则表达式解析 XML 是坏消息。 XML 不是正则语言,因此没有正则表达式可以正确处理它。因此,你写的任何东西都会变得很糟糕且脆弱。

但是,XML确实有类似于正则表达式的东西,称为xpath.

为了解决你的问题,我会这样做:

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
#process the file as XML
my $twig = XML::Twig -> parsefile ( 'your_file.xml' );

#iterate 'FOLDER' elements
foreach my $folder ( $twig -> get_xpath ('//FOLDER' ) ) {
   #delete any that regex match /RS/
   if ( $folder -> att('NAME') =~ m/RS/ ) { 
      $folder -> delete;
   }
}

#print the result. 
$twig -> set_pretty_print('indented_a');
$twig -> print;

答案4

sed -r '/<FOLDER NAME=.*RS.*>/{ :X N; /<\/FOLDER>/d; bX }' file
<CONTAINER>
  <FOLDER NAME="I_R_INR">
  </FOLDER>
</CONTAINER>

相关内容