移除所有節點!=標籤值

移除所有節點!=標籤值

我知道 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>

相關內容