Angenommen, ich habe eine XML-Datei wie unten beschrieben und möchte den Anwendungsnamen, die Maschine und den Status-Tag-Wert mithilfe von Unix-Befehlen extrahieren und in einem durch Kommas getrennten Format darstellen.
XML-Datei:-
<?xml version="1.0" encoding="UTF-8"?>
<applications>
<application name="Adapter/Code1">
<service name="Code1.par">
<deploymentStatus>Success</deploymentStatus>
<serviceInstance name="Code1-One">
<machine>123</machine>
<status>Running</status>
</serviceInstance>
<serviceInstance name="Code1-Two">
<machine>456</machine>
<status>Running</status>
</serviceInstance>
</service>
</application>
<application name="Adapter/Code2">
<service name="Code2.par">
<deploymentStatus>Success</deploymentStatus>
<serviceInstance name="Code2-One">
<machine>123</machine>
<status>Running</status>
</serviceInstance>
<serviceInstance name="Code2-Two">
<machine>456</machine>
<status>Running</status>
</serviceInstance>
</service>
</application>
</applications>
Ausgabe:-
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
Können Sie mir bitte helfen und mir ein Unixbefehls-/Shell-Skript für diese Aktivität bereitstellen?
Dank im Voraus!!!
Antwort1
Python3.x-Lösung (mitxml.etree.ElementTreeModul):
import xml.etree.ElementTree as ET
tree = ET.parse("test.xml")
root = tree.getroot()
for app in root.findall('application'):
for m,s in zip(app.iter('machine'), app.iter('status')):
print("%s,%s,%s" % (app.get('name'), m.text, s.text))
Die Ausgabe:
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
xmlstarlet+awk(wird zum Gruppieren untergeordneter Knoten für jedes application
Element verwendet) Lösung:
xmlstarlet sel -t -v "//application/@name| .//machine/text()| .//status/text()" -n input.xml
| awk '/Adapter/{app=$0; r=app; c=0; next}
{ if(++c==2){ c=0; print r","$0; r=app } else { r=r","$0 }}'
Die Ausgabe:
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
"//application/@name| .//machine/text()| .//status/text()"
- XPath-Ausdruck zum Abrufen der benötigten Knoten/Adapter/{app=$0; r=app; c=0; next}
- Erfassen jedesapplication
Namens zur weiteren Verkettung
Antwort2
Installierenxidelund verwenden Sie XPath.
Meiner Meinung nach ist der beste Standpunkt serviceInstance
:
xidel f.xml -e '//serviceInstance/string-join((../../@name, machine, status),",")'
Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
Antwort3
Verwenden Sie xmlstarlet
zum Durchlaufen jedes serviceInstance
Knotens:
xmlstarlet sel -t \
-m '//application/service/serviceInstance' \
-v '../../@name' -o , \
-v 'machine' -o , \
-v 'status' -nl \
file.xml
Dies gleicht die serviceInstance
Knoten ab und extrahiert für jeden dieser Knoten das name
Attribut seines übergeordneten Knotens, den machine
Wert des Knotens und den status
Wert des Knotens. Diese werden mit Kommas dazwischen ( -o ,
) und einem Zeilenumbruch am Ende ( -nl
) ausgegeben.
Sie können auch eine CSV-Ausgabe von xq
(vonhttps://kislyuk.github.io/yq/):
xq -r '
.applications.application[] | ."@name" as $name |
.service.serviceInstance[] | [ $name, .machine, .status ] | @csv' file.xml
Antwort4
Wenn es gute Gründe gibt, keine XML-Tools zu verwenden, können Sie Low-Level-Parsing verwenden, solange Ihre Anwendung so trivial bleibt wie Ihr Beispiel:
sed 's/<application name="\([^"]*\)">/\1/
Ta
h
d
:a
/<machine>/!d
G
N
s_.*<machine>\(.*\)</machine>\n\(.*\)\n.*<status>\(.*\)</status>.*_\2,\1,\3_' yourfile.xml