Ich möchte wissen, wie ich den Wert eines Knotens mit den folgenden Pfaden erhalten kann:
config/global/resources/default_setup/connection/host config/global/resources/default_setup/connection/username config/global/resources/default_setup/connection/password config/global/resources/default_setup/connection/dbname
aus dem folgenden XML:
<?xml version="1.0"?> <config> <global> <install> <date><![CDATA[Tue, 11 Dec 2012 12:31:25 +0000]]></date> </install> <crypt> <key><![CDATA[70e75d7969b900b696785f2f81ecb430]]></key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db> <table_prefix><![CDATA[]]></table_prefix> </db> <default_setup> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[pass123]]></password> <dbname><![CDATA[testdb]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[pdo_mysql]]></type> <pdoType><![CDATA[]]></pdoType> <active>1</active> </connection> </default_setup> </resources> <session_save><![CDATA[files]]></session_save> </global> <admin> <routers> <adminhtml> <args> <frontName><![CDATA[admin]]></frontName> </args> </adminhtml> </routers> </admin> </config>
Außerdem möchte ich diesen Wert der Variablen zur weiteren Verwendung zuweisen. Lassen Sie mich Ihre Idee wissen.
Kommentare
- Verwenden Sie bash niemals, um strukturierte Bäume beliebiger Daten zu analysieren. Verwenden Sie einen echten XML-Parser. Ich empfehle XMLStarlet .
- stackoverflow.com/questions/893585/how-to -parse-xml-in-bash
Antwort
Verwenden Sie bash
und xmllint
(wie durch die Tags angegeben):
xmllint --version # xmllint: using libxml version 20703 # Note: Newer versions of libxml / xmllint have a --xpath option which # makes it possible to use xpath expressions directly as arguments. # --xpath also enables precise output in contrast to the --shell & sed approaches below. #xmllint --help 2>&1 | grep -i "xpath"
{ # the given XML is in file.xml host="$(echo "cat /config/global/resources/default_setup/connection/host/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" username="$(echo "cat /config/global/resources/default_setup/connection/username/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" password="$(echo "cat /config/global/resources/default_setup/connection/password/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" dbname="$(echo "cat /config/global/resources/default_setup/connection/dbname/text()" | xmllint --nocdata --shell file.xml | sed "1d;$d")" printf "%s\n" "host: $host" "username: $username" "password: $password" "dbname: $dbname" } # output # host: localhost # username: root # password: pass123 # dbname: testdb
Wenn nur eine XML-Zeichenfolge vorhanden ist und die Verwendung einer temporären Datei vermieden werden soll, sind Dateideskriptoren die richtige Wahl für xmllint
(hier wird /dev/fd/3
als Dateiargument angegeben):
set +H { xmlstr="<?xml version="1.0"?> <config> <global> <install> <date><![CDATA[Tue, 11 Dec 2012 12:31:25 +0000]]></date> </install> <crypt> <key><![CDATA[70e75d7969b900b696785f2f81ecb430]]></key> </crypt> <disable_local_modules>false</disable_local_modules> <resources> <db> <table_prefix><![CDATA[]]></table_prefix> </db> <default_setup> <connection> <host><![CDATA[localhost]]></host> <username><![CDATA[root]]></username> <password><![CDATA[pass123]]></password> <dbname><![CDATA[testdb]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[pdo_mysql]]></type> <pdoType><![CDATA[]]></pdoType> <active>1</active> </connection> </default_setup> </resources> <session_save><![CDATA[files]]></session_save> </global> <admin> <routers> <adminhtml> <args> <frontName><![CDATA[admin]]></frontName> </args> </adminhtml> </routers> </admin> </config> " # exec issue #exec 3<&- 3<<<"$xmlstr" #exec 3<&- 3< <(printf "%s" "$xmlstr") exec 3<&- 3<<EOF $(printf "%s" "$xmlstr") EOF { read -r host; read -r username; read -r password; read -r dbname; } < <( echo "cat /config/global/resources/default_setup/connection/*[self::host or self::username or self::password or self::dbname]/text()" | xmllint --nocdata --shell /dev/fd/3 | sed -e "1d;$d" -e "/^ *--* *$/d" ) printf "%s\n" "host: $host" "username: $username" "password: $password" "dbname: $dbname" exec 3<&- } set -H # output # host: localhost # username: root # password: pass123 # dbname: testdb
Kommentare
- Manpage: xmlsoft.org/xmllint.html
Antwort
Obwohl es bereits viele Antworten gibt, melde ich mich bei xml2
.
$ xml2 < test.xml /config/global/install/date=Tue, 11 Dec 2012 12:31:25 +0000 /config/global/crypt/key=70e75d7969b900b696785f2f81ecb430 /config/global/disable_local_modules=false /config/global/resources/db/table_prefix /config/global/resources/default_setup/connection/host=localhost /config/global/resources/default_setup/connection/username=root /config/global/resources/default_setup/connection/password=pass123 /config/global/resources/default_setup/connection/dbname=testdb /config/global/resources/default_setup/connection/initStatements=SET NAMES utf8 /config/global/resources/default_setup/connection/model=mysql4 /config/global/resources/default_setup/connection/type=pdo_mysql /config/global/resources/default_setup/connection/pdoType /config/global/resources/default_setup/connection/active=1 /config/global/session_save=files /config/admin/routers/adminhtml/args/frontName=admin
Mit ein wenig Magie können Sie diese sogar direkt als Variablen festlegen:
Antwort
Verwenden von xmllint und die Option –xpath ist sehr einfach. Sie können dies einfach tun:
XML_FILE=/path/to/file.xml HOST=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/host)" $XML_FILE USERNAME=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/username)" $XML_FILE PASSWORD=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/password)" $XML_FILE DBNAME=$(xmllint --xpath "string(/config/global/resources/default_setup/connection/dbname)" $XML_FILE
Wenn Sie zum Attribut eines Elements gelangen müssen, ist dies auch mit XPath einfach. Stellen Sie sich vor, Sie haben die Datei:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon name="Turn Off" version="0.10.0" provider-name="Dag Wieërs"> ..snip.. </addon>
Die erforderlichen Shell-Anweisungen wären:
VERSION=$(xmllint --xpath "string(/addon/@version)" $ADDON_XML) AUTHOR=$(xmllint --xpath "string(/addon/@provider-name)" $ADDON_XML)
Antwort
Folgendes funktioniert, wenn es mit Ihren Testdaten ausgeführt wird:
{ read -r host; read -r username; read -r password; read -r dbname; } \ < <(xmlstarlet sel -t -m /config/global/resources/default_setup/connection \ -v ./host -n \ -v ./username -n \ -v ./password -n \ -v ./dbname -n)
Dadurch wird der Inhalt in die Variablen host
, username
, password
und .
Kommentare
- xmlstarlet: Befehl nicht gefunden, daher ist dieser Befehl für mich nicht nützlich: (
- @MagePsycho
bash
bietet keine integrierte Unterstützung für XML-Parsing. Sie benötigen entweder ein Tool, das dies ermöglicht (xmlstarlet, xsltproc, ein modernes Python usw.). , oder Sie können ‚ XML nicht korrekt analysieren. - @CharlesDuffy Gibt es eine Möglichkeit, den Wert zu ermitteln, indem Sie möglicherweise ein Regex-Muster verwenden oder?
- @MagePsycho Sie können einfach xmlstarlet installieren. In jedem Fall sollten Sie niemals regul verwenden ar Ausdrücke zum Parsen von (X) HTML .
- @MagePsycho Ich wollte den gleichen Link posten, den terdon bereits gemacht hat. Kurz gesagt: Nein.
Antwort
Eine reine bash
Funktion, nur für den unglücklichen Fall, wenn Sie nichts Passendes installieren dürfen. Dies kann und wird wahrscheinlich bei komplizierterem XML fehlschlagen:
function xmlpath() { local expr="${1//\// }" local path=() local chunk tag data while IFS="" read -r -d "<" chunk; do IFS=">" read -r tag data <<< "$chunk" case "$tag" in "?"*) ;; "!–-"*) ;; "![CDATA["*) data="${tag:8:${#tag}-10}" ;; ?*"/") ;; "/"?*) unset path[${#path[@]}-1] ;; ?*) path+=("$tag") ;; esac [[ "${path[@]}" == "$expr" ]] && echo "$data" done }
Verwendung :
bash-4.1$ xmlpath "config/global/resources/default_setup/connection/host" < MagePsycho.xml localhost
Bekannte Probleme:
- langsame
- Suche nur nach Tag-Namen
- Keine Dekodierung von Zeichenentitäten
Antwort
In diesem Kommentar werden nur sh / bash-Befehle und -Methoden verwendet! /test.xml ist Ihre XML-Typdatei bei der ersten Frage …
#!/bin/sh cat /test.xml | while read line;do [ "$(echo "$line" | grep "<host>")" ]&& echo "host: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<username>")" ]&& echo "username: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<password>")" ]&& echo "password: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" [ "$(echo "$line" | grep "<dbname")" ]&& echo "dbname: $(echo $line | cut -f3 -d"[" | cut -f1 -d"]")" done
Ausgabe:
host: localhost username: root password: pass123 dbname: testdb
Wenn Sie diese Werte in eine Datei schreiben möchten, verwenden Sie diese Methode:
#!/bin/sh cat /test.xml | while read line;do [ "$(echo "$line" | grep "<host>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/host [ "$(echo "$line" | grep "<username>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/username [ "$(echo "$line" | grep "<password>")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/password [ "$(echo "$line" | grep "<dbname")" ]&& echo "$line" | cut -f3 -d"[" | cut -f1 -d"]" > /config/global/resources/default_setup/connection/dbname done
Diese Methode überschreibt Ihre lokalen Dateien, die nur zum Abrufen von Werten (Ihrer Daten) verwendet werden geht aus den Ausgabedateien verloren)
Antwort
Sie können die PHP-Befehlszeilenschnittstellencodierung in Bash-Skripten verwenden, um mehrere komplexe Aufgaben zu verarbeiten Skripte, die sich tatsächlich über mehrere Codierungszeilen erstrecken. Versuchen Sie zunächst, Ihre Lösung mithilfe von PHP-Skripten zu erstellen, und übergeben Sie die Parameter später im CLI-Modus. Auf diese Weise können Sie die hervorragende Verwendung von XML-Parsern steuern.
In der Umgebung können Sie PHP im Client-Modus über den SSH / Shell-Zugriff verwenden.
php -f yourxmlparser.php
Jetzt mache alle Dinge in deiner PHP-Datei. Verwenden Sie die Befehlszeilenparameter, die verwendet werden können.
Sie können diese Rückgabewerte sogar der Shell-Umgebung zuweisen, um den Rest Ihrer Shell-Skripte fortzusetzen.
Die andere Möglichkeit ist die Verwendung von | grep-Option, um Ihren erforderlichen Wert in der XML-Datei abzugleichen, wenn Sie sich ziemlich sicher sind, dass sich die Struktur Ihrer XML-Datei im Laufe der Zeit nicht ändert.