it-swarm.com.de

Wie kann man XML mit Shellscript analysieren?

Ich möchte wissen, wie eine XML-Datei am besten mit Shellscript analysiert werden kann.

  • Sollte man es von Hand machen?
  • Existiert eine Bibliothek der dritten Ebene?

Wenn du es schon geschafft hättest, wenn du mich wissen lassen könntest, wie du es geschafft hast

60
Spredzy

Sie könnten versuchen xmllint

Das Programm xmllint analysiert eine oder mehrere XML-Dateien, die in der Befehlszeile als xmlfile angegeben sind. Abhängig von den ausgewählten Optionen werden verschiedene Arten von Ausgaben gedruckt. Es ist nützlich, um Fehler sowohl im XML-Code als auch im XML-Parser zu erkennen

Sie können Elemente im XML-Dokument mit der Option --pattern nach xpath auswählen.

Unter Mac OS X (Yosemite) wird es standardmäßig installiert.
Wenn Ubuntu noch nicht installiert ist, können Sie apt-get install libxml2-utils

76
Joel

Hier ist ein voll funktionsfähiges Beispiel.
Wenn Sie nur E-Mail-Adressen extrahieren, können Sie Folgendes tun:
1) Angenommen, die XML-Datei spam.xml entspricht

<spam>
<victims>
  <victim>
    <name>The Pope</name>
    <email>[email protected]</email>
    <is_satan>0</is_satan>
  </victim>
  <victim>
    <name>George Bush</name>
    <email>[email protected]</email>
    <is_satan>1</is_satan>
  </victim>
  <victim>
    <name>George Bush Jr</name>
    <email>[email protected]</email>
    <is_satan>0</is_satan>
  </victim>
</victims>
</spam>

2) Sie können die E-Mails abrufen und mit diesem kurzen Bash-Code verarbeiten:

#!/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

Ergebnis dieses Beispiels ist:

0 [email protected]
1 [email protected]
2 [email protected]

Wichtiger Hinweis:
Verwenden Sie dies nicht für ernsthafte Angelegenheiten. Dies ist in Ordnung, um herumzuspielen, schnelle Ergebnisse zu erzielen, grep zu lernen usw., aber Sie sollten auf jeden Fall einen XML-Parser für die Produktion suchen, lernen und verwenden (siehe Michas Kommentar unten).

22
aesede

Es gibt auch xmlstarlet (das auch für Windows verfügbar ist).

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

11
tim

Ich bin überrascht, dass niemand xmlsh erwähnt hat. Das Leitbild:

Eine Befehlszeilen-Shell für XML Basierend auf der Philosophie und dem Design der Unix-Shells

xmlsh bietet eine vertraute Skriptumgebung, die jedoch speziell für die Skripterstellung von XML-Prozessen zugeschnitten ist.

Eine Liste von Shell-ähnlichen Befehlen wird bereitgestellt hier .

Ich verwende den Befehl xed häufig, was sed für XML entspricht und XPath -basiertes Suchen und Ersetzen ermöglicht.

10
user49310

Versuchen Sie sgrep . Es ist nicht klar, was Sie genau versuchen, aber ich würde sicherlich nicht versuchen, einen XML-Parser in bash zu schreiben.

8
Keith

Haben Sie xml_grep installiert? Bei einigen Distributionen handelt es sich um einen Perl-basierten Dienstprogrammstandard (der auf meinem CentOS-System vorinstalliert war). Anstatt ihm einen regulären Ausdruck zu geben, geben Sie ihm einen xpath-Ausdruck.

7
frankc

Versuchen Sie es mit xpath. Sie können es verwenden, um Elemente aus einem XML-Baum zu analysieren.

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

4
Mark Rose

Ein ziemlich neues Projekt ist das Paket xml-coreutils mit xml-cat, xml-cp, xml-cut, xml-grep, ...

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

4
user321

Dies geht wirklich über die Möglichkeiten von Shell-Skripten hinaus. Shell-Skript und die Standard-Unix-Tools sind in Ordnung, um zeilenorientierte Dateien zu analysieren, aber die Dinge ändern sich, wenn Sie über XML sprechen. Selbst einfache Tags können ein Problem darstellen:

<MYTAG>Data</MYTAG>

<MYTAG>
     Data
</MYTAG>

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

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

Stellen Sie sich vor, Sie möchten ein Shell-Skript schreiben, das die darin enthaltenen Daten lesen kann. Die drei sehr, sehr einfachen XML-Beispiele zeigen alle auf unterschiedliche Weise, wie dies ein Problem sein kann. Die ersten beiden Beispiele entsprechen exakt der Syntax in XML. Dem dritten ist einfach ein Attribut zugeordnet. Der vierte enthält die Daten in einem anderen Tag. Einfache Befehle sed, awk und grep können nicht alle Möglichkeiten erfassen.

Sie müssen eine vollständige Skriptsprache wie Perl, Python oder Ruby verwenden. Jedes dieser Module kann XML-Daten analysieren und den Zugriff auf die zugrunde liegende Struktur erleichtern. Ich benutze XML :: Simple in Perl. Ich brauchte ein paar Versuche, um es zu verstehen, aber es tat, was ich brauchte, und erleichterte meine Programmierung erheblich.

2
David W.

Hier ist eine Funktion, die XML-Name-Wert-Paare und -Attribute in Bash-Variablen konvertiert.

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

1
freethinker

Hier ist eine Lösung mit xml_grep (weil xpath nicht Teil unserer verteilbaren Datei war und ich es nicht allen Produktionsmaschinen hinzufügen wollte) ...

Wenn Sie nach einer bestimmten Einstellung in einer XML-Datei suchen und wenn alle Elemente auf einer bestimmten Baumebene eindeutig sind und keine Attribute vorhanden sind, können Sie diese praktische Funktion verwenden:

# File to be parsed
xmlFile="xxxxxxx"

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

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

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

    # 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 $1 $xmlFile 2>/dev/null | tr -d '\n' | sed -n -e "s/.*$element>[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*<\/$element.*/\1/p"`

    # Return the result
    echo $getXmlSettingResult
}

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

Dies funktioniert mit dieser Struktur:

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

Es wird auch damit funktionieren (aber die Zeilenumbrüche werden nicht beibehalten):

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

Wenn Sie <config> oder <logs> oder <path> dupliziert haben, wird nur der letzte zurückgegeben. Sie können die Funktion möglicherweise so ändern, dass ein Array zurückgegeben wird, wenn mehrere Übereinstimmungen gefunden werden.

Zu Ihrer Information: Dieser Code funktioniert auf RedHat 6.3 mit GNU BASH 4.1.2, aber ich glaube nicht, dass ich etwas Besonderes daran tue, also sollte er überall funktionieren.

HINWEIS: Stellen Sie sicher, dass Sie die richtigen Anführungszeichen verwenden, wenn Sie mit Skripten noch nicht vertraut sind. Alle drei werden in diesem Code verwendet (normales einfaches Anführungszeichen '= Literal, rückwärts einfaches Anführungszeichen `= Ausführen und doppeltes Anführungszeichen" = Gruppe).

1
Ed K