Самый простой способ сделать базовый анализ XML из командной строки Unix - PullRequest
10 голосов
/ 08 февраля 2012

Я ищу XML-файлы, которые имеют определенные свойства. Например, файлы, содержащие следующий шаблон:

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

Для таких файлов я хотел бы проанализировать значение другого тега, например:

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

И распечатайте имя файла вместе с «asdf». Какой самый простой способ сделать это из командной строки?

Одним из подходов, о котором я думал, было просто использовать grep с опцией -l для фильтрации соответствующих файлов, а затем использовать xargs grep для извлечения значения ролей. Однако grep плохо работает с многострочными регулярными выражениями. Я видел другой вопрос, который показал, что это можно сделать с помощью опций -Pzo, но мне не повезло заставить его работать в моем случае. Есть ли более простой подход?

Ответы [ 5 ]

13 голосов
/ 09 февраля 2012

Следующая команда linux использует XPath для доступа к указанным значениям в файле XML

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

Пример вывода для соответствующих файлов XML:

./test1.xml asdf
./test4.xml 1234
1 голос
/ 09 февраля 2012
$ 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>
1 голос
/ 09 февраля 2012

Я разработал пару решений, использующих базовую функциональность perl / awk (в основном парсинг тегов для бедного человека).Если вы видите какие-либо улучшения, использующие только базовую функциональность perl / awk, дайте мне знать.Я избегал иметь дело с многострочными регулярными выражениями, устанавливая флаг, когда вижу определенный тег.Вид неуклюжий, но это работает.

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]}'
0 голосов
/ 09 февраля 2012

Я обычно использую Perl XML :: XSH2 .Вы можете интерактивно обрабатывать XML-файлы или создавать сценарии.Сценарий будет что-то вроде (не проверено):

for my $file in { glob "*.xml" } {
    open $file ;
    my $param_value = //param-value[name="Hosts"] ;
    if $param_value echo $file $value/value ;
}
0 голосов
/ 09 февраля 2012

Согласно ответ на этот вопрос , XMLStarlet кажется очень хорошим для такого рода вещей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...