2012-02-08 20 views
9

Poszukuję plików xml, które mają określone właściwości. Na przykład pliki, które zawierają następujący wzór:Najprostszy sposób na podstawowe parsowanie xml z wiersza poleceń unix

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

dla takich plików, chciałbym przeanalizować wartości innej zmiennej, takich jak:

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

i wydrukować nazwę pliku wraz z "asdf". Jaki jest najprostszy sposób na wykonanie tego z linii poleceń?

Jednym podejściem, o którym myślałem było użycie grep z opcją -l do filtrowania pasujących plików, a następnie użycie xargs grep do wyodrębnienia wartości Role. Jednak grep nie działa dobrze w przypadku wyrażeń regularnych wieloliniowych. Widziałem inne pytanie, które pokazało, że można to zrobić za pomocą opcji -Pzo, ale nie miałem szczęścia, żeby działało w moim przypadku. Czy istnieje prostsze podejście?

+0

Czy jest jakiś szczególny powód, dla którego nie chcesz używać języka skryptowego, takiego jak Perl? – Tom

+0

Nie, rozwiązanie perlowe byłoby świetne, najlepiej kompaktowe jednoliniowe, ale nie wiem, jak najlepiej go napisać. – jonderry

+0

Byłoby pomocne mieć rozwiązanie, które działa tylko z najbardziej podstawowych narzędzi, xmlstarlet, xpath i perl's xpath moduł nie są zainstalowane w systemie, w którym mam zamiar wykonać wyszukiwanie. – jonderry

Odpowiedz

2

Najprostszym sposobem jest użycie Saxon z wiersza poleceń.

Oto przykład użycia XPath on the command line. To, w połączeniu ze skryptem powłoki, wykonałoby dokładnie to, o co prosisz.

+0

To wygląda na najbardziej przenośne rozwiązanie, które jest tym, co potrzeba. –

0

Miałem nadzieję, że rozwiążę twój problem bardziej uważnie, ale zabrakło mi czasu, przepraszam.

W każdym razie - perl ma kilka bardzo dobrych modułów do czytania xml.

W szczególności następujący artykuł, perl and xml on the command line, jest prawdopodobnie przedmiotem zainteresowania.

0

Zwykle używam Perla XML::XSH2. Możesz interaktywnie przetwarzać w nim pliki XML lub je skryptować. Skrypt byłoby coś jak (niesprawdzone):

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

Następujące polecenie Linux używa XPath do dojścia określone wartości w pliku XML

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

Przykâadowa dopasowywania plików XML:

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

Opracowałem kilka rozwiązań przy użyciu podstawowej funkcjonalności perl/awk (w zasadzie analizowanie tagów przez biednych ludzi). Jeśli zauważysz jakieś ulepszenia używając tylko podstawowej funkcjonalności perl/awk, daj mi znać. Uniknąłem radzenia sobie z wyrażeń regularnych wieloliniowych, ustawiając flagę, gdy widzę konkretny tag. Trochę niezgrabne, ale działa.

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

Dochód, wyjaśnij, dlaczego cofnąłeś głos. – 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>