Vorrei sapere come posso ottenere il valore di un nodo con i seguenti percorsi:
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
dal seguente 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>
Inoltre voglio assegnare quel valore alla variabile per un ulteriore utilizzo. Fammi sapere la tua idea.
Commenti
- Non usare mai bash per analizzare alberi strutturati di dati arbitrari. Usa un vero parser XML. Consiglio XMLStarlet .
- stackoverflow.com/questions/893585/how-to -parse-xml-in-bash
Risposta
Utilizzo di bash
e xmllint
(come indicato dai tag):
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
Nel caso in cui ci sia solo una stringa XML e si debba evitare luso di un file temporaneo, i descrittori di file sono la strada da percorrere con xmllint
(che viene fornito /dev/fd/3
come argomento del file qui):
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
Commenti
- Man page: xmlsoft.org/xmllint.html
Risposta
Anche se ci sono già molte risposte, interloquisco con 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
Con un po di magia puoi persino impostarle direttamente come variabili:
Risposta
Utilizzo di xmllint e lopzione –xpath , è molto semplice. Puoi semplicemente farlo:
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
Se hai bisogno di raggiungere lattributo di un elemento, è facile anche usare XPath. Immagina di avere il file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addon name="Turn Off" version="0.10.0" provider-name="Dag Wieërs"> ..snip.. </addon>
Le istruzioni della shell necessarie sarebbero:
VERSION=$(xmllint --xpath "string(/addon/@version)" $ADDON_XML) AUTHOR=$(xmllint --xpath "string(/addon/@provider-name)" $ADDON_XML)
Risposta
Quanto segue funziona quando viene eseguito sui dati del test:
{ 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)
Ciò inserisce il contenuto nelle variabili host
, username
, password
e dbname
.
Commenti
- xmlstarlet: comando non trovato, quindi questo comando non mi è utile: (
- @MagePsycho
bash
non ha alcun supporto integrato per lanalisi XML. È necessario disporre di uno strumento che lo faccia (xmlstarlet, xsltproc, un moderno Python, ecc.) , oppure puoi ‘ t analizzare XML correttamente. - @CharlesDuffy cè un modo per ottenere il valore potrebbe usare il pattern regex o altro?
- @MagePsycho puoi semplicemente installare xmlstarlet. In ogni caso, non usare mai regul espressioni ar per analizzare (X) HTML .
- @MagePsycho Stavo per pubblicare lo stesso link che aveva già fatto terdon. In breve: No.
Risposta
Un bash
puro funzione, solo per lo sfortunato caso in cui non ti è permesso installare qualcosa di appropriato. Questo potrebbe, e probabilmente fallirà, con un XML più complicato:
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 }
Utilizzo :
bash-4.1$ xmlpath "config/global/resources/default_setup/connection/host" < MagePsycho.xml localhost
Problemi noti:
- lento
- cerca solo per nomi di tag
- nessuna decodifica di entità carattere
Risposta
Questo commento usa solo comandi e metodi sh / bash! /test.xml è il tuo file di tipo XML alla prima domanda …
#!/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
output:
host: localhost username: root password: pass123 dbname: testdb
se vuoi scrivere questi valori su file usa questo metodo:
#!/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
questo metodo sovrascriverà i tuoi file locali usati solo ottenendo valori (i tuoi dati andrà perso dai file di output)
Risposta
Puoi usare la codifica dellinterfaccia della riga di comando php negli script bash per gestire diversi complessi script che in realtà si estendono su più righe di codice. Innanzitutto, prova a creare la tua soluzione utilizzando gli script PHP, quindi in seguito passa i parametri utilizzando la modalità CLI. In questo modo, puoi ottenere il controllo sugli utilizzi superbi dei parser XML.
Lambiente sembra che tu possa utilizzare PHP in modalità client tramite laccesso ssh / shell.
php -f yourxmlparser.php
Ora, fai tutte le cose allinterno del tuo file php. Utilizza i parametri della riga di comando che può richiedere.
Puoi persino assegnare quei valori di ritorno allambiente Shell per continuare il resto dei tuoi script di shell.
E laltro modo è usare | opzione grep per abbinare il valore richiesto allinterno del file xml, se sei abbastanza sicuro della struttura del tuo file xml che non cambia nel tempo.