2012-02-08 11 views
9

Sto cercando file xml con determinate proprietà. Ad esempio, i file che contengono il seguente schema:Il modo più semplice per eseguire l'analisi XML di base dalla riga di comando di Unix

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

Per tali file, mi piacerebbe analizzare il valore di un altro tag, come ad esempio:

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

e stampare il nome del file lungo con "asdf". Qual è il modo più semplice per farlo dalla riga di comando?

Un approccio a cui stavo pensando era l'uso di grep con l'opzione -l per filtrare i file corrispondenti, e quindi usare xargs grep per estrarre il valore dei ruoli. Tuttavia, grep non funziona bene con regex multi-line. Ho visto un'altra domanda che mostrava che si poteva fare con le opzioni -Pzo, ma non ho avuto fortuna nel farlo funzionare nel mio caso. C'è un approccio più semplice?

+0

C'è un motivo particolare non si desidera utilizzare un linguaggio di scripting come Perl? – Tom

+0

No, una soluzione perl sarebbe ottima, preferibilmente una linea singola compatta, ma non conosco il modo migliore per scrivere. – jonderry

+0

Sarebbe utile avere una soluzione che gira solo con gli strumenti più basilari, tuttavia xmlstarlet, xpath e xpath non sono installati sul sistema su cui eseguirò la ricerca. – jonderry

risposta

2

Il modo più semplice per me è utilizzare Saxon dalla riga di comando.

Ecco un esempio di utilizzo di XPath on the command line. Questo, combinato con uno script di shell, farebbe esattamente quello che stai chiedendo.

+0

Questa sembra la soluzione più portatile che è quella che io bisogno. –

0

Avevo sperato di risolvere il problema con più attenzione, ma ho perso tempo, mi dispiace.

In ogni caso - perl ha alcuni ottimi moduli per la lettura di xml.

In particolare, il seguente articolo, perl and xml on the command line, è probabilmente di interesse.

0

Di solito uso Perl XML::XSH2. È possibile elaborare file XML in modo interattivo o copiarlo. Lo script sarebbe qualcosa di simile (non testata):

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

il seguente comando Linux utilizza XPath per accedere ai valori specificati all'interno del file XML

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

uscita Esempio per la corrispondenza file XML:

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

Ho elaborato un paio di soluzioni usando la funzionalità base di perl/awk (fondamentalmente l'analisi dei tag da parte dei poveri). Se vedi miglioramenti utilizzando solo la funzionalità base di perl/awk, fammi sapere. Ho evitato di trattare con espressioni regolari multilinea impostando una bandiera con vedo un particolare tag. È un po 'maldestro ma funziona.

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

Downvote, per favore spiega perché hai downvoted. – 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> 
Problemi correlati