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 next
comando 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 xq
envoltorio 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, XML
tiene 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>