Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1587 connectés 

  FORUM HardWare.fr
  Programmation
  Shell/Batch

  [BASH] Récupération et changement string

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[BASH] Récupération et changement string

n°2232891
LeBidule75
I've got the finger !
Posté le 07-07-2014 à 15:51:38  profilanswer
 

Bonjour à tous,
 
Je possède plusieurs fichiers XML. Dans chacun d'entre eux, j'ai quelque chose de ce type :
 
[...]
          <Attribute name="V_volume">-1252141245e-015</Attribute>
          <Attribute name="V_userZ">Default_User</Attribute>
          <Attribute name="majorip">SD25SDSFGH12DSFGH45</Attribute>
          <Attribute name="CESTEST">1215DSJFG5SJDF45REIUFTGOHK1558QSHGJKJLLLGE5R6TJ</Attribute>
        </RootAttributes>
        <Streams>
          <Stream format="1" role="">
          <Attribute name="majorid">D43DC61B00001BB4538EF3A300051112</Attribute>
          <Attribute name="My_user">Default_User</Attribute>
          <Attribute name="CESTEST">26XHCJ12SDH</Attribute>
[...]
 
Ce que j'ai besoin de faire est :
1/ Trouver toutes les lignes qui sont de type <Attribute name="CESTEST">**CONTENU**</Attribute>
2/ Tronquer la valeur **CONTENU** à 18 caractères
3/ Enregistrer l'output
 
Concrètement, je cherche à avoir l'output suivant :
          <Attribute name="V_volume">-1252141245e-015</Attribute>
          <Attribute name="V_userZ">Default_User</Attribute>
          <Attribute name="majorip">SD25SDSFGH12DSFGH45</Attribute>
         <Attribute name="CESTEST">1215DSJFG5SJDF45RE</Attribute>
       </RootAttributes>
        <Streams>
          <Stream format="1" role="">
          <Attribute name="majorid">D43DC61B00001BB4538EF3A300051112</Attribute>
          <Attribute name="My_user">Default_User</Attribute>
          <Attribute name="CESTEST">26XHCJ12SDH</Attribute>
 
J'ai testé avec sed et awk mais le résultat n'est pas probant car j'arrive à obtenir le 1215DSJFG5SJDF45RE mais les balises ont disparues avec :/
 
Merci pour votre aide

mood
Publicité
Posté le 07-07-2014 à 15:51:38  profilanswer
 

n°2232918
Profil sup​primé
Posté le 07-07-2014 à 21:03:14  answer
 

salut,
 

Code :
  1. awk '/<Attribute name="CESTEST">/{split($0,a,"[><]" );$0=a[1]"<"a[2]">"substr(a[3],1,18)"<"a[4]">"}1' fichier.xml

mais bon, si tu dois traiter souvent des fichiers xml, il vaut mieux investir ton temps dans l'apprentissage d'XSLT, xsltproc, ou xmlstarlet.

n°2232922
gilou
Modérateur
Modzilla
Posté le 07-07-2014 à 21:41:12  profilanswer
 

Sous unix (ça peut aussi marcher sous windows, mais en prenant certaines précautions dues aux interprétations des quotes par le shell):
perl -pe 's|(?<=\Q<Attribute name="CESTEST">\E)(.{0,18}+)(.*)(?=\Q</Attribute>\E)|$1|' monfichier.xml
 
A la base c'est un substitute s/// mais je remplace le / habituel par un |, d’où un s||| à cause de la présence d'un / dans la balise fermante.
On cherche un groupe de entre 0 et 18 caractères, de manière greedy, suivi éventuellement d'autres caractères (.{0,18}+)(.*), groupe qu'on va garder
Avec un contexte <Attribute name="CESTEST"> à gauche (?<=\Q<Attribute name="CESTEST">\E)  (le \Q...\E sert a bloquer l'interprétation de caractères comme ayant un sens d'opérateur de la regexp)
et avec un contexte </Attribute> à droite (?=\Q</Attribute>\E)
 
La forme plus conventionnelle (et sans les \Q...\E en fait inutiles sauf pour la lisibilité ici) s/(?<=<Attribute name="CESTEST"> )(.{0,18}+)(.*)(?=<\/Attribute> )/$1/ marche aussi, bien sur, mais est nettement moins lisible.
 
A+,


Message édité par gilou le 07-07-2014 à 21:53:50

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2232931
LeBidule75
I've got the finger !
Posté le 08-07-2014 à 09:49:47  profilanswer
 


 
Merci BEAUCOUP pour votre aide.
Ca fonctionne sur plein de fichiers SAUF (et je viens de découvrir le cas) sur des fichiers xml où les balises se suivent... On parle par exemple de fichier xml de 200ko où toutes les balises sont stockées sur... une seule ligne... Avec ta formule sur ce type de fichier, il va traiter la première balise et s'arrêter. J'aurai besoin que le script poursuive la recherche.
 
Je précise que je ne suis pas auteur de ces fichiers :)

n°2232932
LeBidule75
I've got the finger !
Posté le 08-07-2014 à 09:59:07  profilanswer
 

Pour info, une version fonctionnelle :)
 
cat fichier.xml |\
awk '{
                n=match($0,"\"CESTEST\"" )
                if( n==0)
                {
                                print $0
                }
                else
                {
                                m=index(substr($0,n),">" )
                                o=index(substr($0,m+n),"<" )
                                if(o < 18 )
                                {
                                                print $0
                                }
                                else
                                {
                                                print substr($0,1,m+n+17) substr($0,m+n+o-1)
                                }
                }
}'
 
Merci encore pour votre aide

n°2232939
gilou
Modérateur
Modzilla
Posté le 08-07-2014 à 11:19:56  profilanswer
 

LeBidule75 a écrit :


 
Merci BEAUCOUP pour votre aide.
Ca fonctionne sur plein de fichiers SAUF (et je viens de découvrir le cas) sur des fichiers xml où les balises se suivent... On parle par exemple de fichier xml de 200ko où toutes les balises sont stockées sur... une seule ligne... Avec ta formule sur ce type de fichier, il va traiter la première balise et s'arrêter. J'aurai besoin que le script poursuive la recherche.
 
Je précise que je ne suis pas auteur de ces fichiers :)

Voila pourquoi il faut préciser les choses dans son post initial.
 
Si tu peux avoir plusieurs tags <Attribute...> sur une même ligne, alors il suffit de faire:
perl -pe 's|(?<=\Q<Attribute name="CESTEST">\E)([^<]{0,18}+)([^<]*)(?=\Q</Attribute>\E)|$1|g' monfichier.xml  
le g final c'est pour faire une substitution incrémentale sur la ligne, et remplacer . par [^<] (tout caractère sauf < ) évitera d'être trop greedy et de faire la troncature entre le premier tag ouvrant <Attribute name="CESTEST"> et le dernier tag fermant </Attribute> de la ligne lorsqu'il y a plus d'un tag Attribute par ligne.
Et en dernier, après tests, si tout est ok et qu'on ne veut plus de fichier de backup ajouter l'option -i
perl -i -pe 's|(?<=\Q<Attribute name="CESTEST">\E)([^<]{0,18}+)([^<]*)(?=\Q</Attribute>\E)|$1|g' monfichier.xml  
 
 
Le seul cas de figure restant ou ça pourrait ne pas marcher, c'est si tu as des tags coupés en deux par un retour de ligne, auquel cas il vaut mieux lire tout le fichier d'un coup et non en mode ligne a ligne
Il y a un trick standard pour cela: le flag -0777  
Et pour un match multiline, utiliser l'option de regexp smg et non plus seulement g.
perl -0777 -pe 's|(?<=\Q<Attribute name="CESTEST">\E)([^<]{0,18}+)([^<]*)(?=\Q</Attribute>\E)|$1|smg' monfichier.xml  
Mais je doute que tu aies ceci dans ton fichier source, sinon, cela mérite en fait un traitement plus complexe, au cas ou un saut de ligne intervient dans un tag, etc.
 
A+,

n°2232949
Profil sup​primé
Posté le 08-07-2014 à 12:41:07  answer
 

Citation :

Ca fonctionne sur plein de fichiers SAUF (et je viens de découvrir le cas) sur des fichiers xml où les balises se suivent...


une bonne raison supplémentaire pour privilégier XSLT pour le traitement de fichiers XML !


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Shell/Batch

  [BASH] Récupération et changement string

 

Sujets relatifs
Convertir un element d'une liste en string[Batch] selection d'une partie de chaine de caractère
string dans un fichier netcdfchangement de version de visual studio
récupération d'adresse mac avec j2eeExécuter une macro au changement du contenu d'une cellule sous excel
Script shell pour comparaison de 2 fichier et récupération du résultatpetit_programe en bash
[BASH] Probleme Difference 
Plus de sujets relatifs à : [BASH] Récupération et changement string


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR