#1 Le 30/01/2011, à 09: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
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, à 22:01)
Hors ligne
#2 Le 30/01/2011, à 11: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, à 11: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, à 12: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, à 12: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, à 12: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, à 12: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, à 12:59)
Hors ligne
#8 Le 30/01/2011, à 13: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, à 14: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, à 14:33)
"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)
Hors ligne
#10 Le 06/02/2011, à 22: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