Forum Programmation.shell rehercher puis modifier une ligne dans un fichier

Posté par  .
Étiquettes : aucune
0
23
nov.
2006
Bonjour tout le monde,

Je m'adresse à vous car j'ai un petit problème. je chercher à automatiqer la configuration du fichier httpd.conf d'Apache à travers un script shell.

le but est en effet de pouvoir chercher une ligne particulière dans ce fichier, la modifier et enregistrer les modifications dans le même fichier.

la ligne à rechercher doit être lue à partir d'un fichier texte temp.

je pense aux commandes : awk, grep, sed mais je suis débutante et je vous cache pas je bloque là.

quelqu'un peu m'aider SVP. Merci d'avance et bon courage à tous.
  • # quelques pistes ...

    Posté par  . Évalué à 2.

    D'abord, avant toute modification, il te faut sauvegarder le fichier d'origine: cp ancien_fichier ancien_fichier.sav Ensuite: awk ' { (if $0 ~ "expression_recherchee") { $0=ligne_modifiee } print $0 } ' ancien_fichier >nouveau_fichier.tmp et enfin: cp nouveau_fichier.tmp ancien_fichier.
    • [^] # Re: quelques pistes ...

      Posté par  . Évalué à 2.

      GRRRR! Je recommence :

      D'abord, avant toute modification, il te faut sauvegarder le fichier d'origine:

      cp ancien_fichier ancien_fichier.sav

      Ensuite:

      awk ' {

      (if $0 ~ "expression_recherchee") {

      $0=ligne_modifiee

      }

      print $0

      } ' ancien_fichier >nouveau_fichier.tmp

      et enfin:

      cp nouveau_fichier.tmp ancien_fichier
      • [^] # Re: quelques pistes ...

        Posté par  . Évalué à 2.

        merci beaucoup totof2000 , mais ceci ne modifie pas le contenu de mon fichier, moi je cherche à remplacer la ligne trouvée par une autre.
        • [^] # Re: quelques pistes ...

          Posté par  . Évalué à 1.

          Ben si ... tu travaille dans un fichier temporaire, et à la fin tu le copie sur ton fichier d'origine ... ... Mais tu veux faire quoi plus précisément ?
          • [^] # Re: quelques pistes ...

            Posté par  . Évalué à 1.

            ah ok là je viens de retester , mais ma ligne à modifiée est totalement supprimée.
            • [^] # Re: quelques pistes ...

              Posté par  . Évalué à 1.

              Peux-tu me faire un copier/coller de ton bout de code awk?
            • [^] # Re: quelques pistes ...

              Posté par  . Évalué à 1.

              Je pense avoir compris. As tu mis des " " dans l'expression

              $0= "ligne modifiee"

              ?
            • [^] # Re: quelques pistes ...

              Posté par  . Évalué à 1.

              ouups ! c'était de ma faute, c'est bon maintenant :) merci beaucoup.

              mais j'ai une question encore, en effet la chaine à rechercher est à lire à partir d'un fichier. je peux la récupérer par :
              head -1 mon_fichier

              ma question c'est comment je peux passer le résultat de head a la fonction awk ?
              • [^] # Re: quelques pistes ...

                Posté par  . Évalué à 1.

                j'ai trouvé ça :
                awk -v var="ma_chaine" ' { if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp

                maintenant comment affecter à var la valeur retournée d'une autre commande (head ) au lieu de faire passe la chaine elle même ?

                best regards.
                • [^] # Re: quelques pistes ...

                  Posté par  . Évalué à 1.

                  Si le but est d'exécuter la substitution uniquement sur la premier ligne, tu peux faire :

                  awk -v var="ma_chaine" ' (NR==1) {if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp

                  Ceci n'executera la substitution que sur la premiere ligne

                  Sinon il y a head -1 | awk -v ....
                  • [^] # Re: quelques pistes ...

                    Posté par  . Évalué à 2.

                    Oups ... j'ai compris maintenant ce que tu veux faire ...

                    awk -v var="$(head -1 fichier)" ' (NR==1) {if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp

                    Ca marchera peut-etre.

                    Sinon (pas teste)

                    awk ' BEGIN {getline var <fichier} {if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp
                    • [^] # Re: quelques pistes ...

                      Posté par  . Évalué à 1.

                      sinon, pour info, les solutions proposées par ailleurs avec sed marcheront certainement (sauf utilisation d'options propres à GNU Sed dans les expressions), mais sans l'option -i et en travaillant dans un fichier temporaire.
                      • [^] # Re: quelques pistes ...

                        Posté par  . Évalué à 1.

                        j'ai une toute dernière question :-) j'espère que je vous embête pas trop.

                        maitenant il faut que je fait de même pour la chaine de remplacement, elle aussi à lire à partir du fichier temp (2ème ligne), j'ai essayé ceci :

                        awk -v var="$(head -1 temp)" var2="$(tail -1 temp)" ' { if ($0 ~ var) { $0=var2 } print $0 } ' httpd.conf > httpd.conf.tmp

                        var2 prend la valeur de la deuxième ligne de mon fichier temp (SSLRequire %{ SSL_CLIENT_M_SERIAL} in {00,11,22} )mais j'ai comme même une erreur :

                        awk: cmd. line:1: var2=SSLRequire %{ SSL_CLIENT_M_SERIAL} in {00,11,22}
                        awk: cmd. line:1: ^ parse error
                        awk: cmd. line:1: var2=SSLRequire %{ SSL_CLIENT_M_SERIAL} in {00,11,22}
                        awk: cmd. line:1: ^ parse error

                        est ce que c'est une erreur de syntaxe ?

                        merci 1000...000 fois pour tous.
                        • [^] # Re: quelques pistes ...

                          Posté par  . Évalué à 1.

                          l faut faire awk -v var1=.... -v var2= .....

                          mettre -v a chaque variable que tu ajoutes.
                          • [^] # Re: quelques pistes ...

                            Posté par  . Évalué à 1.

                            ah d'accord, merci beaucoup à vous tous, c'est très gentil de votre part. je vous souhaite très bonne continuation.
                  • [^] # Re: quelques pistes ...

                    Posté par  . Évalué à 1.

                    STP est ce que tu peux me donner plus de précision :
                    là j'ai écrit:

                    head -1 temp | awk -v var ' { if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp

                    mais ça ne marche pas, c'est normale car comment je peux indiquer que la valeur de retour de head représente var ??
                    • [^] # Re: quelques pistes ...

                      Posté par  . Évalué à 1.

                      J'ai compris après coup ce que tu voulais faire et j'ai corrigé ma réponse plus haut.
                  • [^] # Re: quelques pistes ...

                    Posté par  . Évalué à 1.

                    STP est ce que tu peux me donner plus de précision :
                    là j'ai écrit:

                    head -1 temp | awk -v var ' { if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp

                    mais ça ne marche pas, c'est normale car comment je peux indiquer que la valeur de retour de head représente var ??
                    • [^] # Re: quelques pistes ...

                      Posté par  . Évalué à 1.

                      merci bcp toto , ta solution :

                      awk -v var="$(head -1 fichier)" ' (NR==1) {if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp

                      marche très bien, je te remercie et je remercie tous les collègues qui m'ont soutenu. Je suis très impressionnée par votre réactivité. Bon courage à tous le monde.
                      • [^] # Re: quelques pistes ...

                        Posté par  . Évalué à 1.

                        pardon c'était ça ;-)

                        awk -v var="$(head -1 temp)" ' { if ($0 ~ var) { $0="toto" } print $0 } ' httpd.conf > httpd.conf.tmp
                        • [^] # Re: quelques pistes ...

                          Posté par  . Évalué à 2.

                          ouaip, ça marche :)
                          C'est juste dommage que la syntaxe de ton bloc awk soit horrible, mais j'ai déjà écrit ce que j'avais à dire là dessus dans mes commentaires précédents.

                          Il faut juste que tu te rendes bien compte que ta syntaxe actuelle montre que tu n'as pas bien compris le fonctionnement de awk (ce qui n'est pas une critique en soi).

                          Si c'est du one shot et que tu ne comptes plus jamais toucher une ligne de commande de ta vie, c'est pas bien grave. Par contre, si tu vas être amener à utiliser régulièrement ce genre d'outil, je t'invite à t'arracher un peu pour comprendre exactement ce que fait ce bout de script. Ca te fera gagner du temps à l'avenir ...
                • [^] # Re: quelques pistes ...

                  Posté par  . Évalué à 2.

                  Tu peux utiliser un pipe ('|').

                  head -1 fichier | awk ...
                  ou head -1 fichier | sed ...

                  essaie quand même de jeter un oeil au premier tutoriel shell venu (suffit de demander à google), par exemple là : http://marcg.developpez.com/ksh/
                  Parce que là, c'est une question super basique.

                  sinon, ton $0= 'toto' est inutile, tu peux directement faire un print 'toto'
                  en remarque bonus, utilise plus une des solutions proposées en sed. awk s'utilise plutôt quand on veut faire des trucs un peu plus compliquées qu'un simple remplacement.
                  sed -e 's/<motif>/<remplacement>/' fichier > fichier.tmp

                  bon allez, mode sympa on. En sed, je ferais un :
                  head -1 fichier | sed -e 's/ma_chaine/toto/' > fichier.tmp

                  en awk :
                  head -1 fichier | awk '$0 ~ "ma_chaine" { print "toto"}' > fichier.tmp

                  et dans les deux cas, pour finir :
                  mv fichier.tmp fichier
                  • [^] # Re: quelques pistes ...

                    Posté par  . Évalué à 2.

                    mouais, en lisant les autres commentaires, je vois que je répond un peu à côté de la question aussi. Les variables d'environnement du shell sont tout à fait adaptées au problème.
                    motif=`head temp`
                    yapuka (c) utiliser la variable motif en lieu et place de ma_chaine dans la ligne de sed (je laisse totof2000 gérer le awk ;) par exemple :
                    sed -e 's/$motif/toto/' fichier > fichier.tmp

                    si on veut que ça soit un peu illisible, on peut même tout faire en un coup :-)
                    sed -e 's/'`head temp`'/toto/' fichier > fichier.tmp

                    encore une fois, je recomamnde fortement la lecture d'un tutoriel pour t'approprier un peu mieux les possibilités offertes par le shell.
                    • [^] # Re: quelques pistes ...

                      Posté par  . Évalué à 1.

                      c'est vrai que ta raison gaaaaaAab , awk lira tout mon fichier httpd.conf , ligne par ligne et que à chaque fois il va tester le motif et faire traitement si motif est verifié. c'est pas du tout optimisé mais bon j'ai appris des choses comme même :-). bon je vais me tirer les cheveux avec ton sed ;-)

                      voilà mon premier essaie :

                      sed -e 's/"$(head -1 temp)"/toto/' httpd.conf > httpd.conf.tmp

                      mais ceci n'a l'air de ne rien faire. alors peux tu m'aider please.
    • [^] # Re: quelques pistes ...

      Posté par  (site web personnel) . Évalué à 1.

      Je préfère ce genre de truc :)

      sed -i.bak_gt -e '/GraphicalTheme=/s/Human/happygnome-list/' /etc/gdm/gdm.conf
      sed -i.bak_uid -e '/MinimalUID=/s/1000/1001/' /etc/gdm/gdm.conf
      sed -i.bak_wcm -e '/Welcome=/s/true/false/' /etc/gdm/gdm.conf
  • # sed

    Posté par  . Évalué à 1.

    sed 's/plop/mega_totoz/' -i httpd.conf

    le -i permet de travailler sur le même fichier.
    • [^] # Re: sed

      Posté par  . Évalué à 1.

      pour info, toutes les versions de sed n'acceptent pas le -i (seul gnu sed à ma connaissance l'accepte). Attention si le script doit être portable ...
    • [^] # Re: sed

      Posté par  . Évalué à 1.

      j'ai essayer ta fonction Plop mais l'option -i ne passe pas. j'ai l'erreur :
      sed: invalid option -- i

      j'ai essayé avec la syntaxe :

      sed -i 's/plop/mega_totoz/' httpd.conf

      mais j'ai la même erreur.

      merci bcp à tout le monde
      • [^] # Re: sed

        Posté par  . Évalué à 1.

        C'est sous Linux ou un autre OS?
        • [^] # Re: sed

          Posté par  . Évalué à 1.

          je travaille en fait sur un serveur unix.
          • [^] # Re: sed

            Posté par  . Évalué à 1.

            la solution proposée ci-dessous marchera peut-être sans le -i et en redirigeant la sortie vers un fichier temporaire.
          • [^] # Re: sed

            Posté par  . Évalué à 1.

            Attention, la version de l'OS est importante. par exemple, awk n'a pas le même comportement sous AIX et Solaris .... certaines fonctions ne sont pas implémentées dans le awk de solaris et il faut dans ce cas utiliser nawk ... Dans ce cas un truc du genre ci dessous devrait faire l'affaire :

            AWK="/usr/bin/awk"

            [ "$(uname -s)" == "SunOS" ] && AWK="/usr/bin/nawk" puis invocation de la commande par

            ${awk} -v var="ma variable" .....
      • [^] # Re: sed

        Posté par  . Évalué à 2.

        Ca t'apprendra à poser des questions correctes, et faire perdre du temps à tout le monde.

        Je ne suis pas devin, et tu es sur un site GNU/linux, donc sans précision de ta part, par défaut, on utilise les outils gnu.

        sinon, pour ton problème, il faut utiliser un fichier temporaire, comme l'a très bien expliqué totof2000

        Cordialement,
        • [^] # Re: sed

          Posté par  . Évalué à 1.

          euh ... pour un débutant c'est pas forcément évident de savoir que sed sous linux ne se comporte pas comme sed sous un autre unix ... c'est pour ça que, en général, je m'efforce d'apporter une solution portable (ou alors je précise que telle ou telle option n'est valable que sous GNU truc ... ).

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.