Убрать всеузлы != значение тега

Убрать всеузлы != значение тега

Я знаю, что 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-парсера. Например, используяXMLStarletв командной строке:

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

Связанный контент