Eliminar todonodos! = valor de etiqueta

Eliminar todonodos! = valor de etiqueta

Sé que los analizadores xml son la forma ideal de hacerlo, pero ninguno está disponible ni se puede agregar a mi entorno.

Tomemos XML que sigue la siguiente estructura:

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

En un script bash, deseo eliminar todos los nodos donde <FOLDER NAME=coinciden *RS*O eliminar todos los nodos donde<FOLDER NAME != $var_folder

¡Cualquier ayuda muy apreciada!

Respuesta1

Esto debería hacerlo:

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

Por cada línea que coincida con el patrón entre los dos /caracteres, se ejecuta el código en {}. N también lleva la siguiente línea al espacio del patrón, y luego d elimina todo antes de pasar a la siguiente línea. Esto funciona en cualquier archivo compatible con POSIX sed.

Pruebe lo siguiente para eliminar cada línea entre <FOLDER NAME=.*RS.*>y </FOLDER.>:

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

El nextcomando detiene el procesamiento de la coincidencia actual. Siga eso con un simple print.

Respuesta2

Deberías hacer esto con un analizador XML. Por ejemplo, usandoXMLStarleten la línea de comando:

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

O,

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

Tenga en cuenta que estos dos no son equivalentes ya que el primer ejemplo realiza una coincidencia de subcadena mientras que el segundo realiza una coincidencia exacta.


Con el xqenvoltorio alrededor 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>

Respuesta3

Bien, en serio: analizar XML con expresiones regulares esmalas noticias. XML NO es un lenguaje regular, por lo que ninguna expresión regular puede manejarlo correctamente. Como resultado, todo lo que escriba será complicado y frágil.

Sin embargo, XMLtiene algo similar a las expresiones regulares, llamado xpath.

Para abordar su problema, lo haría así:

#!/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;

Respuesta4

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

información relacionada