Как разобрать XML с помощью shellscript? [дубликат]


этот вопрос уже есть ответ здесь:

  • Как разобрать XML в Bash? 14 ответов

Я хотел бы знать, что было бы лучшим способом проанализировать XML-файл с помощью shellscript ?

  • нужно ли делать это вручную ?
  • существует ли библиотека третьего уровня ?

Если вы уже сделали это, если вы могли бы дать мне знать, как вам удалось это сделать

11 52

11 ответов:

вы могли бы попробовать xmllint

программа xmllint анализирует один или несколько XML-файлы, указанные в командной строку как XML-файл. Он печатает различные типы выхода, в зависимости от выбранные параметры. Это полезно для обнаружение ошибок как в XML-коде, так и в XML парсере itse

Он позволяет выбирать элементы в XML-документе с помощью xpath, используя параметр --pattern.

на Mac OS X (Yosemite) он устанавливается с помощью по умолчанию.
В Ubuntu, если он еще не установлен, вы можете запустить apt-get install libxml2-utils

вот полный рабочий пример.
Если это только извлечение адресов электронной почты, вы можете просто сделать что-то вроде:
1) Предположим, что XML-файл спам.XML-это как

<spam>
<victims>
  <victim>
    <name>The Pope</name>
    <email>pope@vatican.gob.va</email>
    <is_satan>0</is_satan>
  </victim>
  <victim>
    <name>George Bush</name>
    <email>father@nwo.com</email>
    <is_satan>1</is_satan>
  </victim>
  <victim>
    <name>George Bush Jr</name>
    <email>son@nwo.com</email>
    <is_satan>0</is_satan>
  </victim>
</victims>
</spam>

2) Вы можете получить электронные письма и обрабатывать их с помощью этого короткого кода bash:

#!/bin/bash
emails=($(grep -oP '(?<=email>)[^<]+' "/my_path/spam.xml"))

for i in ${!emails[*]}
do
  echo "$i" "${emails[$i]}"
  # instead of echo use the values to send emails, etc
done

результат этого примера:

0 pope@vatican.gob.va
1 father@nwo.com
2 son@nwo.com

важное замечание:
Не используйте это для серьезных дел. Это нормально для игры, получения быстрых результатов, изучения grep, так далее. но вы должны наверняка ищите, изучайте и используйте XML-парсер для производства (см. комментарий Михи ниже).

есть также xmlstarlet (который также доступен для Windows).

http://xmlstar.sourceforge.net/doc/xmlstarlet.txt

Я удивлен, что никто не упомянул xmlsh. Заявление о миссии:

оболочка командной строки для XML на основе философии и дизайна Оболочки Unix

xmlsh предоставляет знакомую среду сценариев, но в частности специально для сценариев xml-процессов.

список оболочек, как команды предоставляются здесь.

Я использую xed команда много, что эквивалентно к sed для XML, и позволяет XPath поиск и замена.

попробовать sgrep. Не совсем понятно, что вы пытаетесь сделать, но я, конечно, не буду пытаться написать XML-парсер в bash.

У вас установлен xml_grep? Это стандарт утилиты на основе perl для некоторых дистрибутивов (он был предварительно установлен в моей системе CentOS). Вместо того, чтобы давать ему регулярное выражение, вы даете ему выражение xpath.

довольно новый проект представляет собой XML-пакет coreutils в формате XML-кошка, в XML-СР, в XML-вырезать, в формате XML-файлов, ...

http://xml-coreutils.sourceforge.net/contents.html

попробуйте использовать xpath. Вы можете использовать его для анализа элементов из xml-дерева.

http://www.ibm.com/developerworks/xml/library/x-tipclp/index.html

Это действительно выходит за рамки возможностей сценария оболочки. Сценарий оболочки и стандартные инструменты Unix хороши при разборе линейных ориентированных файлов, но все меняется, когда вы говорите о XML. Даже простые теги могут представлять проблему:

<MYTAG>Data</MYTAG>

<MYTAG>
     Data
</MYTAG>

<MYTAG param="value">Data</MYTAG>

<MYTAG><ANOTHER_TAG>Data
</ANOTHER_TAG><MYTAG>

представьте, что вы пытаетесь написать сценарий оболочки, который может считывать данные, заключенные в нем . Три очень, очень простых примера XML показывают разные способы, которыми это может быть проблемой. Первые два примера являются точно таким же синтаксисом в XML. Третий просто атрибут, прикрепленный к нему. Четвертый содержит данные в другом теге. Просто sed,awk и grep команды не могут поймать все возможности.

вам нужно использовать полномасштабный язык сценариев, такой как Perl, Python или Ruby. Каждый из них имеет модули, которые могут анализировать XML-данные и облегчать доступ к базовой структуре. Я использую XML:: Simple в Perl. Мне потребовалось несколько попыток, чтобы понять это, но он сделал то, что мне нужно, и сделал моей программе много облегчающий.

вот функция, которая преобразует пары имя-значение XML и атрибуты в переменные bash.

http://www.humbug.in/2010/parse-simple-xml-files-using-bash-extract-name-value-pairs-and-attributes/

вот решение с использованием xml_grep (потому что xpath не был частью нашего дистрибутива, и я не хотел добавлять его ко всем производственным машинам)...

Если вы ищете определенную настройку в XML-файле, и если все элементы на данном уровне дерева уникальны, и нет атрибутов, то вы можете использовать эту удобную функцию:

# File to be parsed
xmlFile="xxxxxxx"

# use xml_grep to find settings in an XML file
# Input (): path to setting
function getXmlSetting() {

    # Filter out the element name for parsing
    local element=`echo  | sed 's/^.*\///'`

    # Verify the element is not empty
    local check=${element:?getXmlSetting invalid input: }

    # Parse out the CDATA from the XML element
    # 1) Find the element (xml_grep)
    # 2) Remove newlines (tr -d \n)
    # 3) Extract CDATA by looking for *element> CDATA <element*
    # 4) Remove leading and trailing spaces
    local getXmlSettingResult=`xml_grep --cond  $xmlFile 2>/dev/null | tr -d '\n' | sed -n -e "s/.*$element>[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*<\/$element.*//p"`

    # Return the result
    echo $getXmlSettingResult
}

#EXAMPLE
logPath=`getXmlSetting //config/logs/path`
check=${logPath:?"XML file missing //config/logs/path"}

Это будет работать с этой структурой:

<config>
  <logs>
     <path>/path/to/logs</path>
  <logs>
</config>

Он также будет работать с этим (но это не будет держать новые строки):

<config>
  <logs>
     <path>
          /path/to/logs
     </path>
  <logs>
</config>

Если у вас есть дубликат или или , то он вернет только последний. Вероятно, вы можете изменить функцию, чтобы вернуть массив, если он находит несколько совпадений.

FYI: этот код работает на RedHat 6.3 с GNU BASH 4.1.2, но я не думаю, что я делаю что-то конкретное, поэтому должен работать везде.

Примечание: Для тех, кто новичок в сценарии, убедитесь, что вы используете правильные типы кавычек, все три используются в этом код (обычная одинарная кавычка '=литерал, обратная одинарная кавычка ' =execute и двойная кавычка "=group).