Comment analyser XML en utilisant shellscript? [dupliquer]

cette question a déjà une réponse ici:

  • comment analyser XML en Bash? 14 réponses

j'aimerais savoir quelle serait la meilleure façon d'analyser un fichier XML en utilisant shellscript ?

  • Doit-on le faire à la main ?
  • Existe-t-il une bibliothèque de troisième niveau ?

Si vous avez déjà si vous pouviez laissez-moi savoir comment avez-vous réussi à le faire

52
demandé sur Steven Penny 2011-01-13 15:42:10

11 réponses

Vous pouvez essayer de xmllint

le programme xmllint part un ou plusieurs Fichiers XML, spécifiés sur la commande ligne xmlfile. Il imprime divers les types de sortie, selon le les options sélectionnées. Il est utile pour détection des erreurs à la fois dans le code XML et dans L'analyseur XML itse

il vous permet de sélectionner des éléments dans le XML doc par xpath, en utilisant l'option --pattern.

sur Mac OS X (Yosemite), il est installé par défaut.

Sur Ubuntu, s'il n'est pas déjà installé, vous pouvez lancer apt-get install libxml2-utils

68
répondu Joel 2016-05-27 02:19:27

voici un exemple complet.

Si c'est seulement l'extraction des adresses email vous pourriez juste faire quelque chose comme:

1) supposons que le spam du fichier XML.xml est comme

<spam>
<victims>
  <victim>
    <name>The Pope</name>
    <email>pope@vatican.gob.va</email>
    <is_satan>0</is_satan>
  </victim>
  <victim>
    <name>George Bush</name>
    <email>father@nwo.com</email>
    <is_satan>1</is_satan>
  </victim>
  <victim>
    <name>George Bush Jr</name>
    <email>son@nwo.com</email>
    <is_satan>0</is_satan>
  </victim>
</victims>
</spam>

2) Vous pouvez obtenir les e-mails et les traiter avec ce code bash court:

#!/bin/bash
emails=($(grep -oP '(?<=email>)[^<]+' "/my_path/spam.xml"))

for i in ${!emails[*]}
do
  echo "$i" "${emails[$i]}"
  # instead of echo use the values to send emails, etc
done

résultat de cet exemple est:

0 pope@vatican.gob.va
1 father@nwo.com
2 son@nwo.com

remarque Importante:

Ne l'utilisez pas pour des choses sérieuses. C'est OK pour jouer autour, obtenir des résultats rapides, apprendre grep, etc. mais vous devez certainement rechercher, apprendre et utiliser un analyseur XML pour la production (voir le commentaire de Micha ci-dessous).

20
répondu aesede 2016-08-26 15:49:42

Il ya aussi xmlstarlet (qui est disponible pour Windows ainsi).

http://xmlstar.sourceforge.net/doc/xmlstarlet.txt

11
répondu tim 2011-01-13 15:57:05

je suis surpris que personne n'ait mentionné xmlsh . La déclaration de mission:

un shell de ligne de commande pour XML basé sur la philosophie et la conception de la Unix Shells

xmlsh fournit un environnement de script familier, mais spécifiquement adapté au script des processus xml.

une liste de commandes shell similaires est fournie ici .

j'utilise la commande xed qui est l'équivalent de sed pour XML, et permet la recherche basée sur XPath et remplace.

10
répondu user49310 2013-01-31 07:48:34

Essayer sgrep . Ce n'est pas clair exactement ce que vous essayez de faire, mais je n'essaierais sûrement pas d'écrire un analyseur XML dans bash.

8
répondu Keith 2011-01-13 12:46:47

avez-vous des xml_grep installé? C'est une norme d'utilité perl basée sur certaines distributions (elle est venue pré-installée sur mon système CentOS). Plutôt que de les donner une expression régulière, vous lui donnez une expression xpath.

7
répondu frankc 2011-01-13 17:05:47

un projet assez nouveau est le paquet xml-coreutils avec xml-cat, xml-cp, xml-cut, xml-grep, ...

http://xml-coreutils.sourceforge.net/contents.html

4
répondu user321 2011-01-13 18:29:39

essayez xpath. Vous pouvez l'utiliser pour analyser les éléments d'un arbre xml.

http://www.ibm.com/developerworks/xml/library/x-tipclp/index.html

3
répondu Mark Rose 2012-02-21 20:18:44

c'est vraiment au-delà des capacités du script shell. Shell script et les outils Unix standard sont bons pour analyser les fichiers orientés ligne, mais les choses changent quand vous parlez de XML. Même les étiquettes simples peuvent présenter un problème:

<MYTAG>Data</MYTAG>

<MYTAG>
     Data
</MYTAG>

<MYTAG param="value">Data</MYTAG>

<MYTAG><ANOTHER_TAG>Data
</ANOTHER_TAG><MYTAG>

imaginez essayer d'écrire un script shell qui peut lire les données contenues dans . Les trois exemples très, très simplement XML montrent tous de différentes façons que cela peut être un problème. Les deux premiers exemples sont la même syntaxe en XML. Le troisième a un attribut attaché à elle. La quatrième contient les données dans une autre balise. Les commandes simples sed , awk et grep ne peuvent pas saisir toutes les possibilités.

vous devez utiliser un langage de script complet comme Perl, Python ou Ruby. Chacun de ces modules peut analyser des données XML et faciliter l'accès à la structure sous-jacente. J'ai utilisé XML:: Simple en Perl. Il m'a fallu quelques essais pour comprendre, mais il a fait ce dont j'avais besoin, et fait ma programmation beaucoup plus facile.

2
répondu David W. 2011-01-13 16:34:29

Voici une fonction qui convertira les paires nom-valeur XML et les attributs en variables de bash.

http://www.humbug.in/2010/parse-simple-xml-files-using-bash-extract-name-value-pairs-and-attributes /

1
répondu freethinker 2011-01-17 03:12:44

Voici une solution utilisant xml_grep (parce que xpath ne faisait pas partie de notre distribuable et que je ne voulais pas l'ajouter à toutes les machines de production)...

si vous recherchez un paramètre spécifique dans un fichier XML, et si tous les éléments à un niveau d'arbre donné sont uniques, et qu'il n'y a pas d'attributs, alors vous pouvez utiliser cette fonction pratique:

# File to be parsed
xmlFile="xxxxxxx"

# use xml_grep to find settings in an XML file
# Input (): path to setting
function getXmlSetting() {

    # Filter out the element name for parsing
    local element=`echo  | sed 's/^.*\///'`

    # Verify the element is not empty
    local check=${element:?getXmlSetting invalid input: }

    # Parse out the CDATA from the XML element
    # 1) Find the element (xml_grep)
    # 2) Remove newlines (tr -d \n)
    # 3) Extract CDATA by looking for *element> CDATA <element*
    # 4) Remove leading and trailing spaces
    local getXmlSettingResult=`xml_grep --cond  $xmlFile 2>/dev/null | tr -d '\n' | sed -n -e "s/.*$element>[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*<\/$element.*//p"`

    # Return the result
    echo $getXmlSettingResult
}

#EXAMPLE
logPath=`getXmlSetting //config/logs/path`
check=${logPath:?"XML file missing //config/logs/path"}

cela fonctionnera avec cette structure:

<config>
  <logs>
     <path>/path/to/logs</path>
  <logs>
</config>

il fonctionnera aussi avec ceci (mais il ne gardera pas les nouvelles lignes):

<config>
  <logs>
     <path>
          /path/to/logs
     </path>
  <logs>
</config>

si vous avez dupliqué ou ou , alors il ne retournera que le dernier. Vous pouvez probablement modifier la fonction pour retourner un tableau s'il trouve plusieurs correspondances.

FYI: ce code fonctionne sur RedHat 6.3 avec GNU BASH 4.1.2, mais je ne pense pas que je fasse quelque chose de particulier à cela, donc devrait fonctionner partout.

NOTE: pour toute personne nouvelle au script, faire bien sûr, vous utilisez les bons types de guillemets, tous les trois sont utilisés dans ce code (guillemet simple normal '=littéral, guillemet simple en arrière `=execute, et guillemet double "=group).

1
répondu Ed K 2012-11-27 20:31:15