web-dev-qa-db-fra.com

Extraire la valeur XML dans le script bash

J'essaie d'extraire une valeur d'un document XML qui a été lue dans mon script en tant que variable. La variable d'origine, $ data, est la suivante:

<item> 
  <title>15:54:57 - George:</title>
  <description>Diane DeConn? You saw Diane DeConn!</description> 
</item> 
<item> 
  <title>15:55:17 - Jerry:</title> 
  <description>Something huh?</description>
</item> 

et je souhaite extraire la valeur du premier titre, donc

15:54:57 - George:

J'ai utilisé la commande sed:

title=$(sed -n -e 's/.*<title>\(.*\)<\/title>.*/\1/p' <<< $data)

mais cela ne donne que la deuxième valeur de titre:

15:55:17 - Jerry:

Est-ce que quelqu'un sait ce que j'ai mal fait? Merci!

36
Pete

Comme Charles Duffey a déclaré, les analyseurs XML sont mieux analysés avec des outils d'analyse XML appropriés. Pour un travail ponctuel, ce qui suit devrait fonctionner.

grep -oPm1 "(?<=<title>)[^<]+"

Tester:

$ echo "$data"
<item> 
  <title>15:54:57 - George:</title>
  <description>Diane DeConn? You saw Diane DeConn!</description> 
</item> 
<item> 
  <title>15:55:17 - Jerry:</title> 
  <description>Something huh?</description>
$ title=$(grep -oPm1 "(?<=<title>)[^<]+" <<< "$data")
$ echo "$title"
15:54:57 - George:
68
jaypal singh

XMLStarlet ou un autre moteur XPath est l'outil approprié pour ce travail.

Par exemple, avec data.xml contenant les éléments suivants:

<root>
  <item> 
    <title>15:54:57 - George:</title>
    <description>Diane DeConn? You saw Diane DeConn!</description> 
  </item> 
  <item> 
    <title>15:55:17 - Jerry:</title> 
    <description>Something huh?</description>
  </item>
</root>

... vous pouvez extraire uniquement le premier titre avec les éléments suivants:

xmlstarlet sel -t -m '//title[1]' -v . -n <data.xml

Essayer d'utiliser sed pour ce travail est compliqué . Par exemple, les approches basées sur les expressions rationnelles ne fonctionneront pas si le titre a des attributs; ne gérera pas les sections CDATA; ne reconnaîtra pas correctement les mappages d'espace de noms; ne peut pas déterminer si une partie du XML documenté est commentée; ne déchaînera pas les références d'attribut (comme changer Brewster &amp; Jobs à Brewster & Jobs), et ainsi de suite.

22
Charles Duffy

Je suis d'accord avec Charles Duffy pour dire qu'un analyseur syntaxique XML approprié est la bonne solution.

Mais quant à ce qui ne va pas avec votre commande sed (ou l'avez-vous fait exprès?).

  • $data n'a pas été cité, donc $data est soumis au fractionnement de Word de Shell, à l’extension du nom de fichier, entre autres. L'une des conséquences est que l'espacement dans l'extrait de code XML n'est pas préservé.

Donc, étant donné votre structure XML spécifique, cette commande modifiée sed devrait fonctionner

title=$(sed -ne '/title/{s/.*<title>\(.*\)<\/title>.*/\1/p;q;}' <<< "$data")

Essentiellement, pour la ligne contenant title, extrayez le texte entre les balises, puis quittez (pour ne pas extraire le 2nd <title>)

7
doubleDown