Pages : 1
#1 Le 28/10/2019, à 10:37
- Gulian
Parser XML Bash [Résolu]
Bonjour à tous,
Je début le bash, et j'ai décidé de tenter de programmer un parser XML en Bash.
Le fichier a parser :
https://www.w3schools.com/xml/plant_catalog.xml
Voici mon code :
#!/bin/bash
common="";
botanical="";
zone="";
light="";
price="";
availability="";
while read line
do
if echo $line |grep "<COMMON>" -q
then
common=`echo -n $line | sed 's/<[^>]*>//g'`
elif echo $line |grep "<BOTANICAL>" -q
then
botanical=`echo -n $line | sed 's/<[^>]*>//g'`
elif echo $line |grep "<ZONE>" -q
then
zone=`echo $line | sed 's/<[^>]*>//g'`
elif echo $line |grep "<LIGHT>" -q
then
light=`echo $line | sed 's/<[^>]*>//g'`
elif echo $line |grep "<PRICE>" -q
then
price=`echo $line | sed 's/<[^>]*>//g'`
elif echo $line |grep "<AVAILABILITY>" -q
then
availability=`echo $ine | sed 's/<[^>]*>//g'`
fi
if echo $line |grep "</PLANT>" -q
then
echo "$common;$botanical;$zone"
fi
done
Jusqu'ici tout va bien, le problème vient juste du dernier echo. L'affichage ne se fait pas bien, j'obtiens un résultat de la sorte :
;4anguinaria canadensis
;3quilegia canadensis
;4altha palustris
;4altha palustris
;3icentra cucullaria
;3sarum canadense
;4epatica americana
;4epatica americana
;4risaema triphyllum
;3odophyllum peltatum
;3hlox divaricata
;3hlox divaricata
;7laytonia Virginica
;5rillium grandiflorum
;5rillium grandiflorum
;4rythronium americanum
;4rythronium americanum
;4rythronium americanum
;6nemone blanda
;6nemone blandawer
;4onarda didyma
;4onarda didyma
;Annualkia hirta
;4anunculus
;4anunculus
;Annualias tuberosa
;Annualilla
;3 - 5hera
;4entiana
;4entianaian
;Annualnium caeruleum
;Annualnium caeruleum
;Annualholzia californica
;Annualtheonr
;Annualfuga
;2obelia cardinalis
Je suppose un probleme avec le ';' dans le echo, mais rien de concluant ...
Auriez-vous un conseil a me donner ?
Merci bien
Dernière modification par Gulian (Le 28/10/2019, à 12:54)
Hors ligne
#2 Le 28/10/2019, à 11:59
- pingouinux
Re : Parser XML Bash [Résolu]
Bonjour,
Les lignes du fichier .xml se terminent par \r\n au lieu de \n.
Pour supprimer le caractère excédentaire, tu peux ajouter cette ligne en début de boucle :
line=$(sed 's/\r//' <<<"$line")
D'autre part, il y a une faute de frappe à la ligne n°36 ($ine au lieu de $line).
availability=`echo $ine | sed 's/<[^>]*>//g'`
Ajouté :
Au lieu d'ajouter une ligne en début de boucle, tu peux aussi modifier tes sed.
Par exemple :
common=`echo -n $line | sed -r 's/.*>(.*)<.*/\1/'`
Dernière modification par pingouinux (Le 28/10/2019, à 12:35)
Hors ligne
#3 Le 28/10/2019, à 12:52
- Gulian
Re : Parser XML Bash [Résolu]
Merci !
L'erreur était bien du au \r\n et j'ai corrigé la faute de frappe haha
J'aurai pu chercher des heures dans mon code ...
Je te remercie pour la réponse !
Hors ligne
#4 Le 28/10/2019, à 17:18
- kamaris
Re : Parser XML Bash [Résolu]
Tu peux indiquer directement à la commande read que le délimiteur de ligne est \r\n au lieu de \n, par l'option -d $'\r\n'.
Tu pourrais aussi utiliser un tableau associatif pour factoriser un peu ton code :
#!/bin/bash
declare -A tags=( [COMMON]='' [BOTANICAL]='' [ZONE]='' \
[LIGHT]='' [PRICE]='' [AVAILABILITY]='' )
while read -rd $'\r\n' line; do
for tag in "${!tags[@]}"; do
grep -q "<$tag>" <<< "$line" \
&& tags[$tag]=$(sed 's/<[^>]*>//g' <<< "$line")
done
grep -q '</PLANT>' <<< "$line" \
&& echo "${tags[COMMON]};${tags[BOTANICAL]};${tags[ZONE]}"
done < "$1"
Ce script s'appelle en passant en argument le fichier xml à parser.
Ensuite, une fois que tu l'as exécuté, tu peux faire l'expérience suivante : remplacer les grep par des tests équivalents en bash :
#!/bin/bash
declare -A tags=( [COMMON]='' [BOTANICAL]='' [ZONE]='' \
[LIGHT]='' [PRICE]='' [AVAILABILITY]='' )
while read -rd $'\r\n' line; do
for tag in "${!tags[@]}"; do
[[ $line == *"<$tag>"* ]] && tags[$tag]=$(sed 's/<[^>]*>//g' <<< "$line")
done
[[ $line =~ '</PLANT>' ]] && echo "${tags[COMMON]};${tags[BOTANICAL]};${tags[ZONE]}"
done < "$1"
et tu l'exécutes à nouveau : tu devrais voir une petite différence au niveau du temps de traitement .
PS : et puis, quand tu en es là, tu peux essayer de remplacer le sed par une substitution équivalente en bash, et là, tu vas voir ton script s'envoler .
Dernière modification par kamaris (Le 28/10/2019, à 18:32)
Hors ligne
#5 Le 28/10/2019, à 18:43
- Watael
Re : Parser XML Bash [Résolu]
et quand tu auras fini, tu passeras à un vrai parser de XML :
xmlstarlet sel -T -t -m "//CATALOG/PLANT" -v "concat(COMMON,';',BOTANICAL,';',ZONE)" --nl /tmp/plant_catalog.xml
il ne faut pas vous laisser influencer par cet exercice (stupide) : un fichier XML ne se parse jamais en bash. c'est pataud. c'est lent. ce n'est vraiment pas fait pour ça.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#6 Le 28/10/2019, à 20:06
- kamaris
Re : Parser XML Bash [Résolu]
Je début le bash, et j'ai décidé de tenter de programmer un parser XML en Bash.
Il n'y a pas de jamais en matière d'exercice, on fait simplement ce qu'on veut
Cet exercice en vaut bien d'autres.
Hors ligne
#7 Le 28/10/2019, à 20:45
- Watael
Re : Parser XML Bash [Résolu]
c'est stupide de donner en exercice de parser en shell une sortie versatile, telle que ls, xml, json
comme je l'ai dit, ça laisse entendre que c'est un bon usage de cet outil.
vis cruciforme, tournevis plat ...
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne