2017-10-16 5 views
-1

je les données XML suivantes:Remplacer les valeurs XML dans bash sous Linux

<info> 
    <data> 
     <name>my_image</name> 
     <value>site.com/image1.img</value> 
    </data> 
    <data> 
     <name>my_link</name> 
     <value>site.com/p_info</value> 
    </data> 
</info> 

Je veux remplacer tous les site.com à siteimag.com de chaque valeur mon_image (juste pour les attributs de Mon_image).

Ainsi, le résultat sera:

<info> 
    <data> 
     <name>my_image</name> 
     <value>siteimag.com/image1.img</value> 
    </data> 
    <data> 
     <name>my_link</name> 
     <value>site.com/p_info</value> 
    </data> 
</info> 

Comment peut-il être fait avec la commande sed?

Merci.

+0

xml avec l'analyse syntaxique sed est mauvaise idée – RomanPerekhrest

Répondre

1
sed '/my_image/{n;s/site.com/siteimag.com/}' file 

Brève explication,

  • /my_image/: recherche la ligne contenait "mon_image"
  • Une fois la chaîne recherchée,
    • lire la ligne suivante en utilisant la commande n.
    • s/site.com/siteimag.com/: faire la substitution
1

Le même document XML peut être écrit et formaté de différentes façons, donc utiliser un outil simple de texte comme sed mettre à jour, serait très fragile et facile casser.

E.g. juste ajouter une ligne vide entre name et value, va briser le script sed naïf ci-dessus:

<data> 
    <name>my_image</name> 

    <value>site.com/image1.img</value> 
</data> 

Il ne peut pas vraiment aussi suivre la structure XML, et remplacera simplement toute référence site.com, s'il y a un modèle my_image dans la ligne ci-dessus, même si elle est dans un commentaire:

<data> 
    <name>my_link</name> <!-- Used to be "my_image" --> 
    <value>site.com/p_info</value> 
</data> 

il y a littéralement des centaines d'autres façons, peuvent être modifiés le code XML source, sans en changer le sens, pour le faire casser ou entraîner un faux remplacement . Pour éviter cela, vous devez utiliser un outil compatible avec XML, pour effectuer le remplacement, par ex. xmlstarlet:

xmlstarlet ed \ 
-u "//data/name[text()='my_image']/../value" \ 
-x "concat(substring-before(.,'site.com'),'sitemag.com',substring-after(.,'site.com'))"| 
data.xml 
0

La bonne manière est d'utiliser parseurs XML comme xmlstarlet:

xmlstarlet ed -u "//data/name[text()='my_image']/following-sibling::value" \ 
-v "$(sed 's/site/&imag/' <(xmlstarlet sel -t -v "//data/name[text()='my_image']/following-sibling::value" file.xml))" file.xml 

La sortie:

<?xml version="1.0"?> 
<info> 
    <data> 
    <name>my_image</name> 
    <value>siteimag.com/image1.img</value> 
    </data> 
    <data> 
    <name>my_link</name> 
    <value>site.com/p_info</value> 
    </data> 
</info>