Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 30/01/2011, à 10:59

spirou91

[Résolu] [Bash] Changement d'une ligne dans un fichier

Bonjour,

Je cherche à faire un script bash qui pourrais modifier automatiquement une ligne précise de quelques 200 fichiers.

Mon problème est précisément celui-ci: les fichiers que je cherche à modifier sont en Xml.
La ligne à modifier n'est pas constante, mais est précédée d'un attribu tel:

<TextView text="Exemple"  /> (autres données...)

Je cherche à modifier Exemple, qui se trouve entre les deux "", précédées du mot text=.
Tout en sachant que le reste du fichier contient également d'autres données, mais en aucun cas text=. Je dois également conserver mes autres données se trouvant sur la meme ligne.

En cherchant un peu, j'ai finalement constitué cette commande:

grep text= fichier.xml | sed -e 's/"/"ExempleModifie" <!--/3' -e 's/"/-->/5'

Celui ci transforme la ligne en ceci:

<TextView text="ExempleModifie" <!-- Exemple -->  /> (autres données...)

Mais je ne parviens pas à modifier le fichier pour enregistrer la nouvelle ligne produite.

Une autre solution était de parcourir tout le fichier, de le réécrire dans un autre en traitant la ligne nécessaire. Mais voila, les commandes <!-- --> (qui correspondent à un commentaire en Xml) ne sont pas reconnues. Le fichier est alors inutilisable...

Voila, je pense que la description de mon problème est complète smile
En résumé, est-il possible de modifier les données comprises entre les "", précédées d'une balise précise?

Merci de m'aider

Dernière modification par spirou91 (Le 06/02/2011, à 23:01)

Hors ligne

#2 Le 30/01/2011, à 12:49

pode

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

Il ne faut pas utiliser grep, car c'est cette commande qui restreint le traitement aux lignes qui contiennent le pattern recherché.
Au vu du besoin exprimé, tu peux utiliser directement sed ou perl de la façon suivante :

$ sed -i -e 's/text="Exemple"/text="ExempleModifie"/' fichier.xml 
$ perl -pi -e 's/text="Exemple"/text="ExempleModifie"/' fichier.xml

L'option -i permet de faire du "remplacement sur place" (à condition d'avoir les droits en écriture suffisants dans le répertoire où se trouve le fichier à modifier).

Hors ligne

#3 Le 30/01/2011, à 12:53

gl38

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

Il me semble que cette ligne fait le boulot

sed -e 's/\"/\"ExempleModifie\" \<!-- /' -e 's/\"/ --\>/3' toto.xml >toto1.xml 

Reste à faire une boucle pour balayer tous tes fichiers xml et
à faire des
mv toto1.xml toto.xml

Cordialement,
Guy

Hors ligne

#4 Le 30/01/2011, à 13:18

sr40150

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

Salut chez moi ça marche, je remplace uniquement le terme Entreprise par TOTO dans un fichier avec :

cat fichier.txt | sed "s/Entreprise/TOTO/" fichier.txt > fichiertmp.txt
rm fichier.txt
mv fichiertmp.txt fichier.txt

En espérant que cela aura aidé.

Bon courage.

Hors ligne

#5 Le 30/01/2011, à 13:27

Zakhar

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

C'est vraiment super moche d'utiliser sed pour modifier du XML !..

Si vous utilisiez de produit fait pour ça comme Xalan (Licence libre Apache - XSLT1.0) ou Saxon (celui Open Source - XSLT2.0)

sed sur du XML c'est s'exposer à plein d'erreurs selon comment le XML a été produit.


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#6 Le 30/01/2011, à 13:32

gl38

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

N'empêche qu'il n'y a rien de tel pour faire un traitement par lots que la ligne de commande.

Cordialement,
Guy

Hors ligne

#7 Le 30/01/2011, à 13:58

spirou91

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

Merci pour vos réponses,

Je me suis un peu mal exprimé au niveau de mon problème:
les différents fichiers peuvent contenir:

<TextView text="Exemple"  /> (autres données...)
ou encore
<Blabla text="Exemple2"  /> (autres données...)

A savoir que le contenu "Exemple" de l'attribu text= n'est pas une constante. La seule chose qui est constante est le terme text="..."

Et les autres données peuvent également contenir des "" donc je ne peux pas tous les modifier ^^

Le problème est donc un peu plus complexe quand-meme ;-)

Pour ce qui est de faire les boucles sur les fichiers, ca, je m'en occupe :-)
A défaut de me donner la ligne de commande à utiliser, on peux toujours m'expliquer la démarche

Merci à vous,
Cordialement,

Dernière modification par spirou91 (Le 30/01/2011, à 13:59)

Hors ligne

#8 Le 30/01/2011, à 14:23

pode

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

Par exemple :

perl -pi -e 's/(text=")(.*?)(")/$1ExempleModifie$3/g' fichier.xml

wildcard . : n'importe quel caractère
wildcard * : 0 ou n fois
( associé à ) : pour faire des groupes récupérables dans la deuxième partie de la commande avec les back reference $1, $2, $3, ...
? qui suit un * : pour éviter que perl ne soit "glouton" (Exemple de gloutonnerie : <Balise1 text="Exemple1"> <Balise2 text="Exemple2"> devient <Balise1 text="ExempleModifie">)
/g : le remplacement s'appliquera sur toutes les occurrences du pattern d'un même ligne

Hors ligne

#9 Le 30/01/2011, à 15:12

Zakhar

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" version="2.0" encoding="UTF-8" omit-xml-declaration="no"/>

<!-- identity template -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- your template -->
<xsl:template match="@text">
   <xsl:attribute name="text">Nouvelle valeur</xsl:attribute>
</xsl:template>

</xsl:stylesheet>

Voila, tu remplaces la valeur "Nouvelle valeur" par ce que tu as envie d'y mettre.

Ne touche pas au 1er template, c'est le template dit "identity", qui copie à l'identique tout ton arbre XML. Le deuxième template étant une sélection plus "fine" il a priorité lorsqu'un nœud qui y est spécifié est trouvé. Et donc lorsqu'un attribut tel que spécifié est trouvé, c'est ce second template qui s'applique (priorité) et non le premier.

La clause "match" peut bien sûr être complexifiée si toutefois tu ne cherchais pas que les attributs text, ou par exemple seulement les attributs text de noeuds particuliers.
Par exemple, tu peux ne sélectionner que les attributs text d'un noeud qui s'appelle TextView, dans ce cas tu ferais :

match="@text[local-name(..)='TextView']"

Exécution avec saxon

java -jar "/usr/share/saxonb/saxon9.jar" -o dest.xml transform.xsl source.xml

Ca suppose que :
- tu as téléchargé saxon, et posé dans le répertoire indiqué
- tu as copié/collé le source ci-dessus dans transform.xsl
- ton fichier xml source s'appelle source.xml
- le résultat sera dans dest.xml

Bien sur, tu peux adapter les noms en fonction des chemins réels.

Ensuite avec une boucle shell tu adaptes tout ça.

Dernière modification par Zakhar (Le 30/01/2011, à 15:33)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#10 Le 06/02/2011, à 23:01

spirou91

Re : [Résolu] [Bash] Changement d'une ligne dans un fichier

J'ai utilisé la solution de pode

Merci à tous de m'avoir aidé

Hors ligne