IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Bash et parsing XML pour supprimer les balises contenant une chaine


Sujet :

Shell et commandes GNU

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut Bash et parsing XML pour supprimer les balises contenant une chaine
    Bonjour,

    Ma question du jour concerne le parsing d'un fichier XML.

    Le contexte est le suivant : Je dois modifier à la volée des fichiers XML que je reçois avant de les intégrer. Ces fichiers contiennent des noms de serveurs, dont le nommage est fait pour la prod alors que je suis sur des serveurs de test (pour la translation d'adresses IP c'est résolu), en revanche, je dispose de moins de serveurs(machines virtuelles) qu'en prod et il me faudrait supprimer automatiquement les balises contenant les adresses IP dont je n'ai pas besoin.

    En conséquence et en résumé :

    1) Je dois absolument le faire en Bash car je dois intervenir sur une plateforme où je ne peux pas trop installer de nouvelles choses : donc ne ne me proposez pas de Perl ou de Python s'il vous plaît...
    2) J'ai commencé à résoudre une partie de ce dont j'ai besoin : la translation d'adresse IP est bonne.
    3) J'ai besoin de supprimer les balises décrivant les serveurs dont je ne veux pas : tous les serveurs sont décrits dans des balises identiques qui se suivent : donc une solution du style suppression SED n'est pas directement applicable.

    Il me faut supprimer toute la balise contenant l'IP du serveur que je souhaite supprimer et le faire en Bash.

    En espérant avoir été clair.

    Merci d'avance.

    Marco.

  2. #2
    Expert confirmé
    Avatar de becket
    Profil pro
    Informaticien multitâches
    Inscrit en
    Février 2005
    Messages
    2 854
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informaticien multitâches
    Secteur : Service public

    Informations forums :
    Inscription : Février 2005
    Messages : 2 854
    Points : 5 915
    Points
    5 915
    Par défaut
    Citation Envoyé par cotmar Voir le message
    Il me faut supprimer toute la balise contenant l'IP du serveur que je souhaite supprimer et le faire en Bash.
    Salut,

    Je ne crois pas trop m'avancer en disant que l'on a pas encore inventer de langage qui est capable de lire dans les pensées.

    Plus sérieusement, ce serait intéressant d'avoir un exemple concret avec le format "complet" du fichier et de la modification souhaitée.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut
    C'est la raison pour laquelle, j'ai pris la peine de faire une description relativement longue en disant ce que je veux et ce que je ne veux pas.
    Ensuite, qu'elle manque de précision c'est possible. Je vais essayer de donner un exemple à l'arrache :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
     
     
     
    <?xml version="1.0" encoding="UTF-8"?>
    <services>
    <description>Titre</description>
    <contrats>
     
    <contrat nom="toto">
       <service nom="toto1" url="http://monip1"></service>
       <service nom="toto2"  url="http://monip2"></service>
    </contrat>
     
    <contrat nom="titi">
       <service nom="titi1" url="http://monip2"></service>
       <service nom="toto2"  url="http://monip2"></service>
    </contrat>
     
    <contrat nom="tutu">
       <service nom="tutu1" url="http://monip1"></service>
       <service nom="toto2"  url="http://monip2"></service>
       <service nom="toto3"  url="http://monip3"></service>
    </contrat>
     
    </contrats>
    </services>
    Là dedans, je veux pourvoir supprimer par exemple ce qui est dans une balise <service></service> qui correspond à l'URL "http://monip3" qui représente une serveur qui n'existe pas dans mon environnement ?

    Tout cela bien entendu en Bash comme dit précédemment (je n'ai pas le droit d'installer Perl ou Python chez moi).

    Par avance je vous remercies, espérant que ça soi plus clair ?

    Marc.

  4. #4
    Expert confirmé
    Avatar de becket
    Profil pro
    Informaticien multitâches
    Inscrit en
    Février 2005
    Messages
    2 854
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informaticien multitâches
    Secteur : Service public

    Informations forums :
    Inscription : Février 2005
    Messages : 2 854
    Points : 5 915
    Points
    5 915
    Par défaut
    Tu as une liste avec ces serveurs quelques part ? Cette liste corresponde à un critère précis ?

  5. #5
    Expert éminent

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Points : 6 276
    Points
    6 276
    Par défaut
    Salut,
    Citation Envoyé par cotmar Voir le message
    donc une solution du style suppression SED n'est pas directement applicable.
    Et pourquoi ça ?
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut
    Citation Envoyé par becket Voir le message
    Tu as une liste avec ces serveurs quelques part ? Cette liste corresponde à un critère précis ?
    Non pas exactement de liste. Je reconstitue une liste à partir d'éléments que récupère. J'ai pu lorsque ça s'est présenté me faire un cas concret d'un des XML à traiter (mais il en existe d'autres).

    Justement pour éviter les manipulations et les recherches fastidieuses j'aimerais faire un script avec CSV du style : "IpProd;IpTest"
    Et éventuellement : "IpProd;ASupprimer" (pour les serveurs qui n'existent pas dans mon environnement).


    J'ai d'une part les serveurs qui existent dans mon environnement et dont il me faut translater l'adresse (remplacer dans le fichier XML) comme dans le premier cas => je l'ai fais et ça marche
    et d'autre part, ceux qui n'existent pas dans mon environnement et qu'il me faut supprimer du XML => C'est ce qui me reste à faire.

    Je pense que ça simplifierait grandement le travail de mon équipe.

    En espérant être plus clair...

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut
    Citation Envoyé par zipe31 Voir le message
    Salut,


    Et pourquoi ça ?
    Si tu as cette solution, je suis preneur ?

  8. #8
    Expert éminent

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Points : 6 276
    Points
    6 276
    Par défaut
    Citation Envoyé par cotmar Voir le message
    Si tu as cette solution, je suis preneur ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed -i.bak '\#http://monip3#d' fichier
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed -i.bak '/monip3/d' fichier
    si le http:// n'est pas obligatoire


    PS. le ".bak" n'est là qu'au cas ou… c'est pour faire une sauvegarde du fichier original.
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut
    Je te remercies Zipe31, mais ce n'est pas le résultat attendu :

    Dans la portion de l'exemple du XML que j'ai cit"é au début de la discussion :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    <contrat nom="tutu">
       <service nom="tutu1" url="http://monip1"></service>
       <service nom="toto2"  url="http://monip2"></service>
       <service nom="toto3"  url="http://monip3"></service>
    </contrat>
    Je souhaite supprimer la ou les balises <service></service> qui encadrent l'URL que je souhaite supprimer.
    Si il n'y a plus de balise <service></service> je souhaite supprimer le <contrat> qui lui est associé...

    Je ne sais pas si j'ai été très clair au départ. Est-ce que c'est mieux ?

  10. #10
    Expert éminent

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Points : 6 276
    Points
    6 276
    Par défaut
    Citation Envoyé par cotmar Voir le message
    Je souhaite supprimer la ou les balises <service></service> qui encadrent l'URL que je souhaite supprimer.
    C'est ce que fait la commande que je t'ai donnée.

    Citation Envoyé par cotmar Voir le message
    Si il n'y a plus de balise <service></service> je souhaite supprimer le <contrat> qui lui est associé...
    Ça ce n'était spécifié nulle part

    Citation Envoyé par cotmar Voir le message
    Je ne sais pas si j'ai été très clair au départ. Est-ce que c'est mieux ?
    Si d'entrée tu avais donné des exemples AVANT => APRÈS, on aurait gagné du temps et gagné surtout en compréhension
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut
    Citation Envoyé par zipe31 Voir le message
    Ça ce n'était spécifié nulle part
    Je reconnais. C'était un oubli de ma part.
    Du coups, aurais tu une solution s'il te plaît ?

    Citation Envoyé par zipe31 Voir le message
    Si d'entrée tu avais donné des exemples AVANT => APRÈS, on aurait gagné du temps et gagné surtout en compréhension
    C'est vrai.
    J'ai donc essayé par la suite de le décrire précisément, mais sans donner d'exemple, sachant que je ne pouvais pas donner le vrai fichier. J'ai donc bricolé un exemple un peut à l'arrache pour mieux faire comprendre ce que je voulais.

    Merci en tous les cas,
    Marco.

  12. #12
    Expert éminent

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Points : 6 276
    Points
    6 276
    Par défaut
    Citation Envoyé par cotmar Voir le message
    Du coups, aurais tu une solution s'il te plaît ?
    Pour supprimer les balises <contrat…></contrat> vides, cette syntaxe devrait le faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed '\#<contrat #{N;\#</contrat>$#d}' fichier
    Mais comme on n'est pas sûr qu'il n'y ait pas des lignes vides résiduelles, mieux vaut privilégier celle-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed '\#<contrat #{:z;N;\#</contrat>$#!bz;\#<contrat [^>]*>\n\{1,\}</contrat>$#d}' fichier
    Tu rajouteras le "-i.bak" ou "-i" qu'une fois que tu auras vérifié que la syntaxe fait bien ce que tu veux.


    Et pour en revenir à la 1ère commande donnée, par précaution, il serait bon de l'écrire de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed -i.bak '\#http://monip3\>#d' fichier
    Le "\>" à la fin de l'adresse IP permet d'éviter de supprimer des adresses IP ayant une racine commune. (192.168.1.11 et 192.168.1.111 par exemple).
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut
    Bonjour,

    Je te remercies. Ca va me permettre de progresser à la fois dans ma commande et mes connaissances par la même occasion.

    Je me suis permis d'intégrer tout ce que tu m'as dis dans un script shell :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
     
     
     
    # ! /bin/bash
     
    #-----------------------------------------------------------------------
    # Mapping des fichiers ".xml"
    # Pour convertir les adresses de prod en adresses de test
    # Exemple de exemple.CSV :
            #xxx.xxx.xxx.xx1:zzz;aaa.aaa.aaa.bb1:ccc
            #xxx.xxx.xxx.xx2:zzz;aaa.aaa.aaa.bb2:ccc
            #xxx.xxx.xxx.xx3:yyy;aaa.aaa.aaa.bb3:ddd
            #xxx.xxx.xxx.xx4:zzz;aaa.aaa.aaa.bb4:ccc
            #xxx.xxx.xxx.xx5:zzz;suppr 	=> Pour marquer la/les ligne(s) à supprimer
    #-----------------------------------------------------------------------
     
    #-----------------------------------------------------------------------
    # Gestion d’erreurs
    #-----------------------------------------------------------------------
    usage()
    {
            echo "$1"
            echo "Usage :
            $0 ficher_de_mapping.txt fichierRecu.xml
     
            Pour supprimer une ligne du fichier veuillez insérer la ligne suivante dans le fichier de mapping : IP_origine:suppr
            Les autres lignes devront etre selon le modèle : IP_origine;IP_destination
            "
            exit $2
    }
     
    #-----------------------------------------------------------------------
    # Programme principal
    #-----------------------------------------------------------------------
     
    # Date du jour pour historiser la version du fichier
    dateSys=$(date '+%Y-%m-%d')
     
    if [ "$#" -ne "2" ]
    then
            usage "Nombre d arguments invalide : " 80
    else
            [ -f "$1" ] || usage "Le premier argument n est pas un fichier" 81
            [ -f "$2" ] || usage "Le second argument n est pas un fichier" 82
     
            # Copie de sécurité du fichier à modifier
            cp $2 $2.old
     
            # Remplacement
            while read line
            do
                    original="$(echo $line | cut -d; -f1)"
                    new="$(echo $line | cut -d; -f2)"
                    sed -i -e "s/${original}/${new}/g" $2
            done < $1
     
            # Pour supprimer les lignes au premier tour
            sed -i.bak -e '/suppr/d' $1
            # Pour supprimer les balises contrats vides
            sed -i.$dateSys '\#<contrat #{:z;N;\#</contrat>$#!bz;\#<contrat [^>]*>\n\{1,\}</contrat>$#d}' $1
    fi
     
    #-----------------------------------------------------------------------
    # Fin
    #-----------------------------------------------------------------------
     
    exit 0
    Merci d'avance pour les remarques.

    Marco.

  14. #14
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    $1 -> "$1", $2 -> "$2", un peu partout.

  15. #15
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    La première ligne du script (ici la 5) qui doit vraiment être la première ligne du fichier est fausse (tout doit être collé: #!/bin/bash).
    Cordialement.

  16. #16
    Expert éminent

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Points : 6 276
    Points
    6 276
    Par défaut
    Salut,
    Citation Envoyé par disedorgue Voir le message
    (tout doit être collé: #!/bin/bash).
    Euh… pas tout à fait, il peut y avoir un espace entre le shebang et le chemin
    $ man woman
    Il n'y a pas de page de manuel pour woman.

  17. #17
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    echo $line | cut -d; -f2
    Ça, ça n'existe pas. Il faut, soit protéger, soit échapper le point-virgule.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $line | cut -d\; -f2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $line | cut -d';' -f2
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  18. #18
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    481
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 481
    Points : 165
    Points
    165
    Par défaut
    Merci de tous ces commentaires.

    A présent, je n'ai qu'un point qui me chagrine : il ne supprime pas le contrat vide.
    Atrement dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
            # Pour supprimer les balises contrats vides
            sed -i.$dateSys '\#<contrat #{:z;N;\#</contrat>$#!bz;\#<contrat [^>]*>\n\{1,\}</contrat>$#d}' $2
    Semble ne pas marcher. Auriez vous une idée ?

    Je n'ai pas compris non plus pour les quotes autour des $1 et $2 ?
    Sinon, j'ai appliqué toutes vos remarques et je vous en remercies.

    Merci d'avance.

  19. #19
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par cotmar Voir le message
    Auriez vous une idée ?
    Rendre optionnel l'espace dans la balise ouvrante ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed -i.$dateSys '\#<contrat[^>]*>#{:z;N;\#</contrat>$#!bz;\#<contrat[^>]*>\n\{1,\}</contrat>$#d}' "$2"
    Citation Envoyé par cotmar Voir le message
    Je n'ai pas compris non plus pour les quotes autour des $1 et $2 ?
    Eh bien il faut en mettre, des quotes, comme dans la ligne de code ci-dessus

  20. #20
    Expert éminent

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Points : 6 276
    Points
    6 276
    Par défaut
    Citation Envoyé par cotmar Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            # Pour supprimer les balises contrats vides
            sed -i.$dateSys '\#<contrat #{:z;N;\#</contrat>$#!bz;\#<contrat [^>]*>\n\{1,\}</contrat>$#d}' $2
    Ben comme toujours, quand on n'a pas les vrais fichiers sous les yeux, on fait avec les données fournies et on suppute…

    Donc, peut être qu'il existe des choses (caractères non-imprimables ou autres) qu'on n'a pas prévu.

    Fais un cat -A ton_fichier et vois si entre les balises <contrat…></contrat> apparaissent des trucs bizarres ou autres…
    $ man woman
    Il n'y a pas de page de manuel pour woman.

Discussions similaires

  1. [RegEx] Regex pour supprimer les balises <input>
    Par chris0938 dans le forum Langage
    Réponses: 4
    Dernier message: 07/06/2010, 16h07
  2. Macro pour supprimer les lettres d'une cellule?
    Par LittleSun dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 26/01/2010, 19h56
  3. pour supprimer les doublons d'une table qcq
    Par lamjed dans le forum Oracle
    Réponses: 7
    Dernier message: 19/12/2008, 16h42
  4. [RegEx] probleme de reference arrière pour supprimer les balises html
    Par Galeenet dans le forum Langage
    Réponses: 1
    Dernier message: 16/10/2007, 23h02
  5. Réponses: 12
    Dernier message: 04/03/2007, 11h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo