2008-10-09 6 views
2

J'ai déjà extrait la balise du document source en utilisant grep, mais maintenant je n'arrive pas à comprendre comment extraire facilement les propriétés de la chaîne. Aussi, je veux éviter d'utiliser des programmes qui ne seraient généralement pas présents sur une installation standard.Comment extraire les propriétés XML à l'aide de scripts shell?

$tag='<img src="http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg" title="Don't we all." alt="Barrel - Part 1" />' 

J'ai besoin de se retrouver avec les variables suivantes

$src="http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg" 
$title="Don't we all." 
$alt="Barrel - Part 1" 

Répondre

1

Je suis allé avec la suggestion de dacracot consistant à utiliser sed bien que je l'aurais préféré s'il me avait donné quelques exemples de code

src=`echo $tag | sed 's/.*src=["]\(.*\)["] title=["]\(.*\)["] alt=["]\(.*\)["].*/\1/'`  
title=`echo $tag | sed 's/.*src=["]\(.*\)["] title=["]\(.*\)["] alt=["]\(.*\)["].*/\2/'` 
alt=`echo $tag | sed 's/.*src=["]\(.*\)["] title=["]\(.*\)["] alt=["]\(.*\)["].*/\3/'` 
+1

avec sed est une approche vraiment, vraiment mauvais - il est fragile et ne sait rien du tout sur la norme XML , et ainsi vous donnera de mauvais résultats en rencontrant des choses comme & amp. Voir la suggestion de Torsten Marek. –

+0

désolé je n'ai pas travaillé sur le script sed pour vous, je n'ai pas eu le temps à ce moment – dacracot

+1

Si vous n'avez pas le temps d'écrire une bonne réponse, alors n'en écrivez pas un. Même si vous le faites, assurez-vous de revenir et de l'éditer plus tard. – ephemient

4

Vous pouvez utiliser xmlstarlet. Ensuite, vous ne devez pas même pour en extraire l'élément vous-même:

$ echo $tag|xmlstarlet sel -t --value-of '//img/@src' 
http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg 

Vous pouvez même transformer cela en fonction

$ get_attribute() { 
    echo $1 | xmlstarlet sel -t -o "&quot;" -v $2 -o "&quot;" 
    } 
$ src=get_attribute $tag '//img/@src' 

Si vous ne voulez pas réanalyser le document plusieurs fois, vous peut aussi faire:

$ get_values() { 
    eval file=\${$#} 
    eval $#=  
    cmd="xmlstarlet sel " 
    for arg in [email protected] 
    do 
     if [ -n $arg ] 
     then 
     var=${arg%%\=*} 
     expr=${arg#*=} 
     cmd+=" -t -o \"$var=&quot;\" -v $expr -o \"&quot;\" -n" 
     fi 
    done 
    eval $cmd $file 
    } 
$ eval $(get_values src='//img/@src' title='//img/@title' your_file.xml) 
$ echo $src 
http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg 
$ echo $title 
Don't we all. 

Je suis sûr qu'il ya une meilleure façon de supprimer le dernier argument d'une fonction shell, mais je ne sais pas.

+0

Oh, alors xmlstarlet peut ne pas être disponible sur une installation standard. Désolé, je pense qu'il était un peu trop tard quand j'ai écrit la réponse ... –

0

Si xmlstarlet est disponible sur une installation standard et la séquence de src-titre-alt ne change pas, vous pouvez utiliser le code suivant ainsi:

tag='<img src="http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg" title="Don'"'"'t we all." alt="Barrel - Part 1" />' 
xmlstarlet sel -T -t -m "/img" -m "@*" -v '.' -n <<< "$tag" 
IFS=$'\n' 
array=($(xmlstarlet sel -T -t -m "/img" -m "@*" -v '.' -n <<< "$tag")) 
src="${array[0]}" 
title="${array[1]}" 
alt="${array[2]}" 

printf "%s\n" "src: $src" "title: $title" "alt: $alt" 
0

Depuis cette bouillonnait encore, il est maintenant mon Xidel qui a 2 caractéristiques qui rendent cette tâche triviale:

  • modèle

    correspondant sur le xml

  • exporter tous les variables adaptées à la coquille

Il devient donc une seule ligne:

eval $(xidel "$tag" -e '<img src="{$src}" title="{$title}" alt="{$alt}"/>' --output-format bash) 
Questions connexes