Shell-Skript zum Extrahieren des Tag-Wertes

Shell-Skript zum Extrahieren des Tag-Wertes

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

https://docs.python.org/3.6/library/xml.etree.elementtree.html?highlight=etree#module-xml.etree.ElementTree


xmlstarlet+awk(wird zum Gruppieren untergeordneter Knoten für jedes applicationElement 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 jedes applicationNamens zur weiteren Verkettung

http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.html

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 xmlstarletzum Durchlaufen jedes serviceInstanceKnotens:

xmlstarlet sel -t \
    -m '//application/service/serviceInstance' \
    -v '../../@name' -o , \
    -v 'machine' -o , \
    -v 'status' -nl \
    file.xml

Dies gleicht die serviceInstanceKnoten ab und extrahiert für jeden dieser Knoten das nameAttribut seines übergeordneten Knotens, den machineWert des Knotens und den statusWert 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

verwandte Informationen