J'aimerais savoir quel serait le meilleur moyen d'analyser un fichier XML à l'aide de shellscript?
Si vous l'avez déjà fait, si vous pouviez me faire savoir comment vous avez réussi à le faire
Vous pouvez essayer xmllint
Le programme xmllint analyse un ou plusieurs fichiers XML, spécifiés sur la ligne de commande sous la forme xmlfile. Il imprime différents types de sortie, en fonction des options sélectionnées. Il est utile pour détecter les erreurs à la fois dans le code XML et dans l'analyseur XML.
Il vous permet de sélectionner des éléments dans la documentation XML par xpath, en utilisant l'option --pattern.
Sur Mac OS X (Yosemite), il est installé par défaut.
Sous Ubuntu, s’il n’est pas déjà installé, vous pouvez exécuter apt-get install libxml2-utils
Voici un exemple de travail complet.
S'il ne s'agit que d'extraire des adresses électroniques, vous pouvez simplement faire quelque chose comme:
1) Supposons que le fichier XML spam.xml ressemble à
<spam>
<victims>
<victim>
<name>The Pope</name>
<email>[email protected]</email>
<is_satan>0</is_satan>
</victim>
<victim>
<name>George Bush</name>
<email>[email protected]</email>
<is_satan>1</is_satan>
</victim>
<victim>
<name>George Bush Jr</name>
<email>[email protected]</email>
<is_satan>0</is_satan>
</victim>
</victims>
</spam>
2) Vous pouvez obtenir les emails et les traiter avec ce code bash:
#!/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
Le résultat de cet exemple est:
0 [email protected]
1 [email protected]
2 [email protected]
Note importante:
Ne l'utilisez pas pour des problèmes graves. C’est acceptable pour jouer, obtenir des résultats rapides, apprendre grep, etc., mais vous devriez définitivement rechercher, apprendre et utiliser un analyseur XML pour la production ( voir le commentaire de Micha ci-dessous).
Il y a aussi xmlstarlet (qui est également disponible pour Windows).
Je suis surpris que personne n'ait mentionné xmlsh . L'énoncé de mission:
Un shell en ligne de commande pour XML basé sur la philosophie et la conception des shells Unix
xmlsh fournit un environnement de script familier, mais spécialement conçu pour les processus de script xml.
Une liste de commandes de type Shell est fournie ici .
J'utilise beaucoup la commande xed
qui équivaut à sed
pour XML et permet la recherche et le remplacement à base de XPath
.
Essayez sgrep . Ce que vous essayez de faire n'est pas clair, mais je n'essaierais sûrement pas d'écrire un analyseur XML en bash.
Avez-vous xml_grep installé? C'est un utilitaire standard basé sur Perl sur certaines distributions (il est venu pré-installé sur mon système CentOS). Plutôt que de lui donner une expression régulière, vous lui donnez une expression xpath.
Essayez d'utiliser xpath. Vous pouvez l'utiliser pour analyser des éléments hors d'une arborescence xml.
http://www.ibm.com/developerworks/xml/library/x-tipclp/index.html
Un nouveau projet est le paquetage xml-coreutils avec xml-cat, xml-cp, xml-cut, xml-grep, ...
C'est vraiment au-delà des capacités du script shell. Le script shell et les outils Unix standard permettent d’analyser des fichiers orientés ligne, mais les choses changent lorsque vous parlez de XML. Même les balises 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 que vous essayez d’écrire un script Shell capable de lire les données contenues dans. Les trois exemples XML très très simplement montrent tous différentes manières dont cela peut poser problème. Les deux premiers exemples correspondent exactement à la même syntaxe XML. Le troisième a simplement un attribut qui lui est attaché. La quatrième contient les données dans une autre balise. Les commandes simples sed
, awk
et grep
ne permettent pas de saisir toutes les possibilités.
Vous devez utiliser un langage de script complet, tel que Perl, Python ou Ruby. Chacun de ces modules possède des modules capables d'analyser les données XML et de faciliter l'accès à la structure sous-jacente. J'ai utilisé XML :: Simple en Perl. Il m'a fallu quelques essais pour le comprendre, mais cela a répondu à mes besoins et a rendu ma programmation beaucoup plus facile.
Voici une fonction qui convertira les paires nom-valeur XML et les attributs en variables bash.
http://www.humbug.in/2010/parse-simple-xml-files-using-bash-extract-name-value-pairs-and-attributes/
Voici une solution utilisant xml_grep (car xpath ne faisait pas partie de notre distribuable et 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 d'un niveau d'arborescence donné sont uniques et en l'absence d'attributs, vous pouvez utiliser cette fonction pratique:
# File to be parsed
xmlFile="xxxxxxx"
# use xml_grep to find settings in an XML file
# Input ($1): path to setting
function getXmlSetting() {
# Filter out the element name for parsing
local element=`echo $1 | sed 's/^.*\///'`
# Verify the element is not empty
local check=${element:?getXmlSetting invalid input: $1}
# 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 $1 $xmlFile 2>/dev/null | tr -d '\n' | sed -n -e "s/.*$element>[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*<\/$element.*/\1/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>
Cela fonctionnera également avec ceci (mais il ne gardera pas les nouvelles lignes):
<config>
<logs>
<path>
/path/to/logs
</path>
<logs>
</config>
Si vous avez des doublons <config>, <journaux> ou <chemin>, alors le dernier ne sera renvoyé. Vous pouvez probablement modifier la fonction pour renvoyer 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 quoi que ce soit, mais devrait fonctionner partout.
REMARQUE: pour les débutants en script, assurez-vous d'utiliser les bons types de guillemets. Les trois sont utilisés dans ce code (guillemet simple normal '= littéral, guillemet simple en arrière `= exécuter et double guillemet" = groupe ".