SED de Linux à Unix

Résolu
Bonjour,

voilà la situation :

la commande suivante ( qui fonctionne très bien sous Linux Ubuntu ) se trouve dans un fichier perl.
elle permet d'insérer dans un fichier une variable à la ligne 13 ...

system "sed i\ '13i$variable' ../dossier/fichier.xsl";

cette même commande ne fonctionne pas sous Unis, HPUNIX pour être précis ... et malgré quelques commandes testées, une petite étude du man je ne trouve pas ... une idée ??

MERCI !! :D
Configuration: Linux
Firefox 2.0.0.11

22 réponses

Résumé de la discussion

Le fil examine la difficulté portable d’insérer une variable à la ligne 13 via sed en mode in-place, fonctionnant sous Linux mais échouant sur HP-UX en raison de la non-portabilité de l’option -i. Plusieurs réponses expliquent que -i n’est pas universel et proposent des solutions alternatives avec Perl, notamment des enchaînements -pi ou -e pour insérer du contenu à une ligne précise. Des extraits montrent comment écrire en Perl une chaîne $var et insérer à la 3e ligne ou modifier le fichier en place, avec variantes utilisant -i.orig et des constructions s/^/$var\n/ si $.==3. En pratique, la portabilité peut être assurée par Perl, évitant les soucis HP-UX; tester les scripts sur l’environnement cible avant déploiement reste toutefois recommandé et prudent.

Bobot (l’IA à votre service)
  1. Modérateur
    Salut,

    Simplement parce que le switch "-i" (in-place) n'est pas portable, il y a que les version de "GNU sed" supérieure à 4.0.5 qui l'implémente...

    ;-))
    1. salut jipicy !

      merci pour ta réponse :)

      en laissant tomber sed, y a t il un autre moyen ( en perl par exepmle ) pour y arriver ??

      merci !
      1. Modérateur
        Re-

        Je suppose que oui, mais pour ça je vais laisser la main à lami20j, perlien en chef s'il en est et qui devrait te pondre un truc en 2 temps 3 mouvements ;-))
      2. Modérateur
        En attendant, jette un œil à cette solution proposée aussi par l'ami lami20j ;-))
      3. @jipicybon .. j'ai regardé ce que tu m'a fait suivre ... malheureusement c'est n'est pas exactement ce que je cherche .. il s'agit d'un remplacement de mot par un autre ..

        moi j'ai un fichier comme celui ci par exemple :

        le
        chat
        dort
        près
        du
        feu

        et je voudrais :

        le
        chat
        noir
        dort
        pres
        du
        feu

        donc une insertion du mot "noir" à la ligne 3 ..

        ca fonctionnais avec ma commande sous ubuntu dans un script perl .. mais là je l'ai porté sous hp ux et ca ne fonctionne pas ..
        merci de vos réponse et peut être de celle de lami20j ;)
    2. merci à toi c'est bien sympa je regarde ca en attendant oui :)
      1. Modérateur
        Re-
        $ cat plop
        le
        chat
        dort
        près
        du
        feu
        
        $ var="noir";fich="$(cat plop)";echo "$fich" | sed "3 i $var" > plop
        
        $ cat plop
        le
        chat
        noir
        dort
        près
        du
        feu
        ;-))
        1. sniff!! :'(

          merci pour ta réponse, mais voilà ce que j'obtiens :

          " sed : Function 3 i cannot be parsed" ...

          ma version d'unix : HPUX 11i version 2

          dur dur ... dire que ca marche tres bien en linux ... je viens de la tester sous ma ubuntu => nikel .. et pas sous hpux ...
        2. @jipicy$Revision: B11.23.0409LR

          donc apparament c'est 4.09 la version de sed et B11.23 celle d'HPUX ...

          :)
      2. Modérateur
        Je pense qu'on va attendre le verdict de lami20j pour ce qui concerne le perl...

        Désolé ;-(
        1. ok, merci en tout cas pour tes réponses, c'est gentil !

          j'ai envoyé un MP à lami20j au cas où il ne tombe pas sur le poste :)
          1. Modérateur
            Salut à vous,

            c'est ça que tu veux faire?
            lami20j@debserv:~/trash$ cat phoenix1984
            le
            chat
            dort
            près
            du
            feu
            lami20j@debserv:~/trash$ perl -ne '$var='noir';s/^/$var\n/ if 3..3;print' phoenix1984
            le
            chat
            noir
            dort
            près
            du
            feu
            lami20j@debserv:~/trash$
            Il faut adapter. Il sera mieux de savoir sur quel fichier tu travailles, ainsi que la condition d'insertion, peut être qu'on sera pas obliger d'utiliser le nombre de ligne.
            1. Modérateur
              ou
              lami20j@debserv:~/trash$ cat phoenix1984
              le
              chat
              dort
              près
              du
              feu
              lami20j@debserv:~/trash$ perl -ne '$var='noir';s/^/$var\n/ if $.==3;print' phoenix1984
              le
              chat
              noir
              dort
              près
              du
              feu
              lami20j@debserv:~/trash$
              
              1. salut ! premiererement merci pour ta réponse !

                pour ce qui est de la condition d'écriture, il n'y en a pas en faite .. je vais essayer d'expliquer clairement. je bosse sur une supervision de cluster oracle en perl.
                différents points sont "surveillés" ( accèssibilité, nombre de listener de la base, état des filesystem, etc ... ). le résultat apparait sur une page html générée d'apres un .xml et .xsl ...
                mon programme perl lance des commandes unix pour récupérer les infos sur les serveurs.

                dans notre cas précis : la condition se fait en amont :

                si le serveur ne répond pas il faut mettre un voyant rouge dans le fichier xsl.
                si le serveur répond il faut mettre un voyant vert dans le fichier xsl.

                d'où mon besoin d'insertion de telle ou telle variable dans le fichier xsl ...

                le mécanisme je l'ai bien compris, et tout fonctionne tres bien depuis une machine linux ... mais lors de la mise en test avant production le tout tourne sous unix ( ca sera le cas à terme ) et là j'ai eu le problème d'insertion ....

                j'espere avoir répondu a ta question ...

                Donc, pour finir, je n'ai meme pas besoin de vérifier sur la ligne est vide ou non .. dans tous les cas je vais insérer une ligne ... c'est juste la variable qui changeras

                ci dessous un extrait de mon xsl

                <?xml version="1.0" encoding="ISO-8859-1"?>
                <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                <xsl:template match="/">
                <html>
                <head>
                <title>Etat du cluster Oracle</title>
                </head>
                <body>
                <center><IMG src="logo.jpg"></IMG></center>
                <h1><center>Etat du cluster Oracle</center></h1>
                <h3><b>Date</b></h3>
                <p><xsl:value-of select="ini/date" /></p><TABLE border='0' width='160%' height='150'><TR><td>
                <h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Disponibilite</b></h3>
                <pre><xsl:value-of select="ini/diag_materiel/ping" /></pre>
                <h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Filesystem locaux 5</b></h3>
                <pre><xsl:value-of select="ini/diag_materiel/filesystem_locaux_5" /></pre>
                <h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Filesystem locaux 6</b></h3>
                <pre><xsl:value-of select="ini/diag_materiel/filesystem_locaux_6" /></pre></td><td>
                <h3><b><IMG src="puce_orangee.gif" align="absmiddle"></IMG> Filesystem NFS</b></h3>
                <pre><xsl:value-of select="ini/diag_materiel/ssh_nfs" /></pre>
                <h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Instances</b></h3>
                <pre><xsl:value-of select="ini/diag_materiel/instances" /></pre>
                <h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Listener</b></h3>
                <pre><xsl:value-of select="ini/diag_materiel/listener" /></pre></td></TR></TABLE>
                </body>
                </html>
                </xsl:template>
                </xsl:stylesheet>

                en gras : les lignes que je dois insérer suite à mes tests ...

                en perl sous linux voilà ce que j'utilisais :

                system "sed -i '13i$ok' ../visuel/clusterwares.xsl"; # insertion à la ligne 13 du fichier .xsl de $ok

                ton code au dessus n'implemente pas le fichier destination par contre ... :s la modif n'apparait que dans le print ... j'ai "bêtement" fait un ">"

                perl -ne '$var='noir';s/^/$var\n/ if $.==3;print' > phoenix1984

                mais ca a tout effacé dans le fichier ...

                merci de ton aide et/ou de celle des autres ;)
                1. Modérateur
                  Salut,

                  je vais regarde de plus près ce soir ;-)

                  dans le print ... j'ai "bêtement" fait un ">"

                  perl -ne '$var='noir';s/^/$var\n/ if $.==3;print' > phoenix1984

                  mais ca a tout effacé dans le fichier ...


                  je suis d'accord toi avec bêtement ;-))

                  il fallait faire
                  perl -ne '$var="noir";s/^/$var\n/ if $.==3;print'  phoenix1984 > autre_fichier
                  ou
                  perl -pi.orig -e '$var="noir";s/^/$var\n/ if $.==3'  phoenix1984 
                  --

                  lami20j
                  1. Modérateur
                    j'espere avoir répondu a ta question ...

                    en fait, ce n'est pas très clair
                    l'emplacement (numéro de ligne) - tu le connais d'avance ou c'est variable?!
                    ce que tu veux insérer je vois que c'est variable.

                    bref, il faut trouver l'emplacement et la ligne qu'il faut insèrer.

                    pour l'instant pour moi ce n'est pas clair

                    donc si tu arrives à me faire comprendre ce que tu vex faire, je pourrai te donner la solution ;-)
                    1. Merci pour le tuyau pour écrire le résultat dans un fichier.

                      C'est vrai que ce n'est pas facile d'expliquer comme ca ..

                      Il faut imaginer cela par modules.

                      Ping - Etat des disques - Listener - Instances Chacun des modules est un fichier perl qui lance des commandes unix, et qui EN FONCTION du résultat écrivent dans le fichier xsl.

                      au début de chaque fichier perl je déclare des variables ( quasiement les même dans chaque module ) pour, selon le résultat de la requête afficher un puce rouge ou une puce verte :

                      # Déclaration variables puces colorées
                      $bad=('<h3><b><IMG src="puce_rouge.gif" align="absmiddle"></IMG> Instances</b></h3>');
                      $ok=('<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Instances</b></h3>');


                      dans l'exemple si dessus c'est pour le programme perl de l'instance ( en gras ), mais appart "instance" le reste est pareil.

                      Ensuite OUI, les numero de ligne pour les insertions est connu et toujours le meme et peut donc être ecrit en dur.

                      En fait je part du fichier xsl "vide" c'est à dire sans les lignes puce rouge - puce verte, et au fur et à mesure de l'exécution de mes programmes perl ca implemente ce fichier .

                      Voilà son état d'origine :

                      1<?xml version="1.0" encoding="ISO-8859-1"?>
                      2<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                      3<xsl:template match="/">
                      4<html>
                      5<head>
                      6<title>Etat du cluster Oracle</title>
                      7</head>
                      8<body>
                      9<center><IMG src="logo.jpg"></IMG></center>
                      10<h1><center>Etat du cluster Oracle</center></h1>
                      11<h3><b>Date</b></h3>
                      12<p><xsl:value-of select="ini/date" /></p><TABLE border='0' width='160%' height='150'><TR><td>
                      13<pre><xsl:value-of select="ini/diag_materiel/ping" /></pre>
                      14<pre><xsl:value-of select="ini/diag_materiel/filesystem_locaux_5" /></pre>
                      15<pre><xsl:value-of select="ini/diag_materiel/filesystem_locaux_6" /></pre></td><td>
                      16<pre><xsl:value-of select="ini/diag_materiel/ssh_nfs" /></pre>
                      17<pre><xsl:value-of select="ini/diag_materiel/instances" /></pre>
                      18<pre><xsl:value-of select="ini/diag_materiel/listener" /></pre></td></TR></TABLE>
                      19</body>
                      20</html>
                      21</xsl:template>
                      22</xsl:stylesheet>


                      chacun des programmes perl va écrire sa ligne dans le fichier, soit pour faire apparaitre puce verte, soit puce rouge ...

                      par exemple le module qui test le ping ecrira toujours une de ces 2 variable à la ligne 13.

                      voici le code des insertion que j'avais sous linux et qui fonctionnaient ;

                      system "sed -i '13i$ok' ../visuel/clusterwares.xsl";
                      => j'ecrivais le contenu de la variable $ok ( puce verte ) à la ligne 13..

                      j'avais la meme commande dans les autres modules ...seul le numero de ligne change 21 par exemple ...
                      system "sed -i '21i$ok' ../visuel/clusterwares.xsl";

                      il me faudrait donc seulement "convertir" cette commande
                      system "sed -i '13i$ok' ../visuel/clusterwares.xsl"; qui marchait sous linux en UNIX ...

                      pas forcement avec sed.

                      Ton exemple de ce matin me va bien, il insert bien le texte, par contre je ne trouve pas la syntaxe pour mettre la commande das fichier perl ..

                      là dans le shell elle fonctionne :

                      perl -pi.orig -e '$var="<h3><b><IMG src='"'puce_verte.gif'"' align='"'absmiddle'"'></IMG> Filesystem locaux5</b></h3>";s/^/$var\n/ if $.==3' ../visuel/clusterwares.xsl

                      dans un fichier toto.sh aussi, mais je ne sais pas comment le formater pour qu'elle soit dans le fichier perl ping.pl par exemple.

                      Voilà, j'espere avoir répondu à tes question. c'est tres sympa en tout cas d'avoir le courage de em lire et d'essayer de me répondre :)

                      ps :

                      du fait de ma variable "compliquée" avec des "<" et des guillemets, j'ai été obligé d'improviser comme tu as pu le voir avec de multiples guillemets autour de puce_verte par exemple , mais ca marche, c'est bon ;)

                      $var="<h3><b><IMG src='"'puce_verte.gif'"' align='"'absmiddle'"'></IMG> Filesystem locaux C7ORA5</b></h3>";
                      1. Modérateur
                        mais je ne sais pas comment le formater pour qu'elle soit dans le fichier perl ping.pl par exemple.

                        dans le script tu peux utiliser l'opérateur q{} pour eviter les multiples guillemets ;-)
                        $bad=q{<h3><b><IMG src="puce_rouge.gif" align="absmiddle"></IMG> Instances</b></h3>}; 
                        --

                        lami20j
                        1. a ok, je ne connaissais pas, très bien, ca marche nickel !! :D

                          j'ai aussi trouvé comment exécutée la commande depuis un fichier perl avec "system"... un peu différent de d'habitude, mais c'eest ok :

                          system q{perl -pi.orig -e '$var=q{<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Filesystem locaux5</b></h3>};s/^/$var\n/ if $.==3' ../visuel/clusterwares.xsl;};

                          on y est presque !!

                          il me reste qu'à détacher le contenu de la variable .. j'ai testé ca sans succès ... je continue à chercher ...

                          $var=(q{<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Filesystem locaux5</b></h3>});
                          system q{perl -pi.orig -e 's/^/$ok\n/ if $.==3' ../visuel/clusterwares.xsl;};


                          merci pour ton aide !!
                          1. Modérateur
                            ce n'est pas avec système que tu dois faire

                            tu peux le faire directement avec perl en utiliseant l'option -i dans
                            #!/usr/bin/perl -i.orig
                            use strict;use warnigns;
                            
                            $ok=q{<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Instances</b></h3>}; 
                            
                            while(<>){
                              s/^/$ok\n/ if $.==3';
                              print;
                            }
                            __END__
                            et tu lances le script avec la commande
                            perl script.pl  ../visuel/clusterwares.xsl
                            --

                            lami20j
                            1. Modérateur
                              j'ai oublié un apostrophe et my
                              #!/usr/bin/perl -i.orig
                              use strict;use warnigns;
                              
                              my $ok=q{<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Instances</b></h3>}; 
                              
                              while(<>){
                                s/^/$ok\n/ if $.==3;
                                print;
                              }
                              __END__
                              1. salut ! oui ne t'inquiete pas j'avais vu. petite faute de frappe sur le warning aussi ;) comme ca au moins ca me fait réfléchir et pas juste faire des copier coller. :)

                                par contre justement ... peut on mettre le fichier source et destination directement dans le code pour ne lancer que script.pl, sans arguments ?

                                je ne comprend pas pourquoi le -i.orig est dans la premiere ligne en commentaire .. :$

                                en tout cas c'est cool de t'occuper des petits débutants comme moi :@)
                                1. Modérateur
                                  pour ne lancer que script.pl, sans arguments ?
                                  oui, c'est possible
                                  je vais regarder un peu plutard

                                  je t'expliquerai aussi -i.orig
                                  1. oui, ne lancer que "script.pl" et que le programme perl insert diretement la ligne dans le fichier voulu ...

                                    en gros comme le dernier code que tu m'a donné, sauf que le nom du fichier source destination soit dans le code.
                                    là le dernier exemple on print le résultat mais on ne l'enregistre pas dans le fichier .. et je ne trouve pas comment faire ..

                                    le truc c'est de faire

                                    -----------------------------------------------------------------------

                                    #!/usr/bin/perl
                                    use strict;

                                    # déclaration des variables
                                    my $ok=q{<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Instances</b></h3>};

                                    insérer la ligne "..blabla $ok " à la ligne 13 par exemple dans le fichier ../visuel/clusterwares.xsl

                                    ------------------------------------------------------------------------

                                    et n'avoir à lancer que perl script.pl

                                    c'est ce que j'arrivais à faire avant sous linux ... :)

                                    merci à toi
                                    1. Modérateur
                                      Salut,

                                      voilà
                                      #!/usr/bin/perl -i.orig
                                      use strict;use warnings;
                                      
                                      @ARGV = qw{../trash/clusterwares.xsl};
                                      my $ok=q{<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Instances</b></h3>};
                                      #
                                      while(<>){
                                              s/^/$ok\n/ if $.==3;
                                              print;
                                      }
                                      __END__
                                      
                                      -i.orig passé en 1ère ligne (QUI N'EST PAS UN COMMENTAIRE même si elle commence avec #)
                                      #! s'appele shebang
                                      Nous pouvons passer des options comme on le fait en ligne de commande

                                      Par exemple au lieu d'écrire use warnings on peut écire
                                      #!/usr/bin/perl -w

                                      si ça te semble bizarre tu peux utiliser la variable $^I ($INPLACE_EDIT avec le module English) qui fait la même chose
                                      #!/usr/bin/perl
                                      use strict;use warnings;
                                      
                                      @ARGV = qw{../trash/clusterwares.xsl};
                                      $^I = ".orig";
                                      
                                      my $ok=q{<h3><b><IMG src="puce_verte.gif" align="absmiddle"></IMG> Instances</b></h3>};
                                      #
                                      while(<>){
                                              s/^/$ok\n/ if $.==3;
                                              print;
                                      }
                                      __END__


                                      • 1
                                      • 2