2012-02-08 19 views
9

Estoy buscando archivos xml que tengan ciertas propiedades. Por ejemplo, los archivos que contienen el siguiente patrón:Manera más simple de hacer un análisis xml básico desde la línea de comandos de Unix

<param-value> 
    <name>Hosts</name> 
    <description>some description</description> 
    <value></value> 
</param-value> 

para este tipo de archivos, me gustaría analizar el valor de otra variable, como por ejemplo:

<param-value> 
    <name>Roles</name> 
    <description>some description</description> 
    <value>asdf</value> 
</param-value> 

e imprimir el nombre del archivo a lo largo con "asdf". ¿Cuál es la forma más simple de lograr esto desde la línea de comando?

Un enfoque en el que estaba pensando era simplemente usar grep con la opción -l para filtrar los archivos coincidentes, y luego usar xargs grep para extraer el valor de Roles. Sin embargo, grep no funciona bien con expresiones regulares multilíneas. Vi otra pregunta que mostraba que se podía hacer con las opciones -Pzo, pero no tuve suerte para que funcionase en mi caso. ¿Hay un enfoque más simple?

+0

¿Hay alguna razón en particular que usted no desea utilizar un lenguaje de programación como Perl? – Tom

+0

No, una solución perl sería genial, preferiblemente una línea compacta, pero no sé cuál es la mejor manera de escribirla. – jonderry

+0

Sería útil tener una solución que funcione con las herramientas más básicas, sin embargo, xmlstarlet, xpath y el módulo xpath de perl no están instalados en el sistema en el que voy a realizar la búsqueda. – jonderry

Respuesta

2

Lo más simple para mí es usar Saxon desde la línea de comandos.

Aquí hay un ejemplo del uso de XPath on the command line. Esto, combinado con un script de shell, haría exactamente lo que estás pidiendo.

+0

Parece la solución más portátil que es lo que necesitar. –

0

Tenía la esperanza de resolver su problema más cuidadosamente, pero me he quedado sin tiempo, lo siento.

Anyway - perl tiene algunos módulos muy buenos para leer xml.

En particular, el siguiente artículo, perl and xml on the command line, es probablemente de interés.

0

Suelo usar Perl's XML::XSH2. Puede procesar archivos XML de forma interactiva en él, o guiarlo. El guión sería algo así como (no probado):

for my $file in { glob "*.xml" } { 
    open $file ; 
    my $param_value = //param-value[name="Hosts"] ; 
    if $param_value echo $file $value/value ; 
} 
12

el siguiente comando Linux utiliza XPath para acceder a los valores especificados en el archivo XML

for xml in `find . -name "*.xml"` 
do 
echo $xml `xmllint --xpath "/param-value/value/text()" $xml`| awk 'NF>1' 
done 

Ejemplo de salida para hacer coincidir los archivos XML:

./test1.xml asdf 
./test4.xml 1234 
1

Trabajé un par de soluciones usando la funcionalidad básica perl/awk (básicamente un análisis de pobre de las etiquetas). Si ve alguna mejora utilizando solo la funcionalidad básica de perl/awk, hágamelo saber. Evité ocuparme de las expresiones regulares de líneas múltiples estableciendo un indicador con una etiqueta en particular. Algo torpe pero funciona.

Perl:

perl -ne '$h = 1 if m/Host/; $r = 1 if m/Role/; if ($h && m/<value>/) { $h = 0; print "hosts: ", $_ =~ /<value>(.*)</, "\n"}; if ($r && m/<value>/) { $r = 0; print "\nrole: ", $_ =~ /<value>(.*)</, "\n" }' 

awk:

awk '/Host/ {h = 1} /Role/ {r = 1} h && /<value>/ {h = 0; match($0, "<value>(.*)<", a); print "hosts: " a[1]} r && /<value>/ {r = 0; match($0, "<value>(.*)<", a); print "\nrole: " a[1]}' 
+4

Voto abajo, explique por qué ha votado negativamente. – jonderry

1
$ xmlstarlet ed -u /param-value/name -v Roles -u /param-value/value -v asdf data.xml 

<?xml version="1.0"?> 
<param-value> 
    <name>Roles</name> 
    <description>some description</description> 
    <value>asdf</value> 
</param-value> 
Cuestiones relacionadas