Shell Script para extrair o valor da tag

0

Suponha que eu tenha um arquivo xml como mencionado abaixo e eu queira extrair o nome do aplicativo, o valor da tag de máquina e status usando comandos unix e apresentá-lo em formato separado por vírgula.

arquivo XML: -

 <?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>

Saída: -

Adapter/Code1,123,Running

Adapter/Code1,456,Running

Adapter/Code2,123,Running

Adapter/Code2,456,Running

Você pode me ajudar a dar um comando unixcommand / shell para fazer esta atividade?

Obrigado antecipadamente !!!

    
por user232796 24.05.2017 / 09:48

3 respostas

2

Python 3.x solução (com o módulo xml.etree.ElementTree ):

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))

A saída:

Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running

link

Solução xmlstarlet + awk (usada para agrupar nós filhos para cada elemento application ):

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 }}'

A saída:

Adapter/Code1,123,Running
Adapter/Code1,456,Running
Adapter/Code2,123,Running
Adapter/Code2,456,Running
  • "//application/@name| .//machine/text()| .//status/text()" - expressão XPath para obter os nós necessários

  • /Adapter/{app=$0; r=app; c=0; next} - capturando cada application nome para outra concatenação

link

    
por 24.05.2017 / 16:39
1

Instale o xidel e use o xpath.

Na minha opinião, o melhor ponto de vista é de 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
    
por 24.05.2017 / 17:59
0

Se você tiver um bom motivo para não usar as ferramentas xml, poderá usar a análise de baixo nível, contanto que seu aplicativo permaneça trivial como seu exemplo:

sed 's/<application name="\([^"]*\)">//
Ta
h
d
:a
/<machine>/!d
G
N
s_.*<machine>\(.*\)</machine>\n\(.*\)\n.*<status>\(.*\)</status>.*_,,_' yourfile.xml
    
por 24.05.2017 / 10:05