Forum Programmation.shell Script pour modifier C++ sources

Posté par  .
Étiquettes : aucune
0
26
sept.
2007
Bonjour,
j'ai une 100ene de fichiers .h et une autre de .cpp à modifier de la facon suivante :
Pour les .h tout ce qui est de cette forme
/**
* Licence
*/
#ifndef TOTO_H
#define TOTO_H

#include "TATA.h"

/**
* @author ...
*/

class TOTO
{ public:
...
}


Par

/**
* Licence
*/
#ifndef TOTO_H
#define TOTO_H

#include "TATA.h"

/**
* @author ...
*/
namespace TITI
{
class TOTO
{ public:
...
}
}

Donc ajouter namespace TITI { et } à des endroits bien précis dans le fichier

Et pour la version cpp, juste un
using namespace TITI

Quelqu'un a une idée comment je peux faire çà en bash ou outils GNU

Merci
  • # sed peut-être ?

    Posté par  . Évalué à 2.

    Perso, je suis super rigoureux sur l'indentation. Si c'était mon code, je sais que je pourrais m'appuyer sur le motif ^class\> pour ajouter namespace titi\n{ et sur le motif ^}$ pour ajouter un \n} dans les .h

    Pour les cpp, s'il y a d'autres directives using, rien de plus simple que d'en rajouter une. Sinon, il faut arriver à identifier un motif qui te permettrait de rajouter ton using à un endroit pertinent. La, ça dépend de ton code.

    Si l'identation de ton code n'est pas 100 % fiable, tu peux p-e te mettre dans une situation maitrisée (au moins pour les éléments qui t'intéressent) en farfouillant dans les options d'indent.
    • [^] # Re: sed peut-être ?

      Posté par  . Évalué à 2.

      C'est pas le probleme l'indentation, mais si tu as des forward declaration ca marche plus... idem si tu as plusieurs declarations de class...
      • [^] # Re: sed peut-être ?

        Posté par  . Évalué à 2.

        si y a plusieurs classes, c'est pas bien grave. sed traitera tout le fichier et donc toutes les déclarations du dit fichier.

        Pour les forward declaration, j'avoue humblement mon ignorance .. je ne sais pas ce que c'est. Et j'ai des petits soucis réseau qui font que google me répond pas.

        un petit brief sur ce que c'est et pourquoi ça pose problème dans ton cas ?
        • [^] # Re: sed peut-être ?

          Posté par  . Évalué à 2.

          un formward declaration ca evite d'inclure dans un .h le .h d"une classe.
          Et ca s'ecrit
          class TATA;
          • [^] # Re: sed peut-être ?

            Posté par  . Évalué à 2.

            ça reste toujours une question de trouver le bon motif.
            ici, en fait, tu n'ajouteras le namespace que pour le motif ^class[^;]*$ et pas le seul motif ^class

            Si tu t'en sors pas avec ça, dis le, j'essaierai de te proposer un script ...
            • [^] # Re: sed peut-être ?

              Posté par  . Évalué à 1.

              Ouais en fait ca doit marcher si tu prends en compte le class * : *
              Maintenant reste à faire çà en sed.

              J'ai l'habitude d'utiliser sed pour faire ce genre de truc :


              for file in `ls *.h` :
              do
              sed -e "s/TOTO/TITI/g' $file > out_tmp
              done


              Alors comment je modifie ca pour prendre en compte ce que tu m'as dit.
              Un il y a 1> le regex et 2> il faut ajouter la ligne namespace titi.

              Meci
              En tout cas
              • [^] # Re: sed peut-être ?

                Posté par  . Évalué à 2.

                heu ... c'est l'heure d'aller manger là ! :)

                la suite cet aprème
              • [^] # Re: sed peut-être ?

                Posté par  . Évalué à 2.

                Je t'invite très fortement à lire un tutoriel sur les regex et/ou sur sed.

                tu pourrais faire un truc comme :
                sed -e 's/^class[^;]*$/namespace titi\n{ \n&/g' -e 's/^}$//' -e 's/^}$/&\n&/'

                quelques rappels rapide pour comprendre. Le caractère ^ représente le début de la ligne, $ : la fin de ligne, & : est remplacé par le motif recherché dans la chaine de substitution, \n : un retour chariot dans la chaine de substitution, < indique un début de mot, et >, une fin de mot. [^;] matche n'importe quel caractère sauf ;

                d'autre part, ton for file in `ls *.h` se remplace avantageusement par for file in *.h.
                Autre remarque, le ls n'étant pas récursif, ça ne fonctionera pas si ton arborescence n'est pas plate. find est là pour t'aider, genre :

                for i in `find . -name '**.h'

                sauf qu'on peut faire encore mieux avec l'option -exec de find, ou, encore mieux, avec xargs et l'option -i de sed (qui indique à sed de travailler directement sur le fichier en entrée)
                find . -name "*.h" | xargs sed -i -e 's/^class[^;]*$/namespace titi\n{ \n&/g' -e 's/^}$//' -e 's/^}$/&\n&/'

                encore quelques petites remarques:
                l'expression 's/^}$/&\n&/' est p-e pas assez fine. Elle dupliquera toutes les lignes ne contenant qu'une accolade fermante. Si ton contient des accolades fermantes qui ne sont pas des fermetures de classes, tu te retrouveras avec trop d'accolades après le traitement.
                Evidemment, il y a des solutions, à base de comptage d'accolades ouvrantes et fermantes, pour ne rajouter des accolades fermantes que quand il le faut.

                Si tu veux pouvoir relancer le script sans risquer de traiter deux fois le même fichier, tu peux rajouter un grep -c "\<namespace titi\>' pour faire quelque chose comme (on respire un grand coup :) :
                find . -name '*.h' | grep -c '\<namespace titi\>' | cut -d ':' -f 1 | xargs sed -i -e 's/^class[^;]*$/namespace titi\n{ \n&/g' -e 's/^}$//' -e 's/^}$/&\n&/'

                bon, ça fait p-e beaucoup ... Si tu prends bien le temps de comprendre chaque améloration que je propose, tu devrais pas mal progression dans ton approche des scripts shell.

                bon courage :)
                • [^] # Re: sed peut-être ?

                  Posté par  . Évalué à 1.

                  Parfait, je vais voir çà
                  Merci a lot
                  • [^] # Re: sed peut-être ?

                    Posté par  . Évalué à 1.

                    C'est pas mal à ceci pres, j'ai changé le sed comme ca :

                    sed -e 's/^class[^;]*$/namespace TITI\n{ \n&/g' -e 's/^#endif$/}\n&\n/'

                    Mais en fait il me faudrait le dernier #endif du fichier ;)

                    Sinon tu es un chef !!
                    • [^] # Re: sed peut-être ?

                      Posté par  . Évalué à 2.

                      ah oui, en fait, tu veux un seul namespace titi par fichier .. ?

                      pour travailler sur la dernière occurence d'un motif dans un fichier, on ne peut pas utiliser une commande qui fonctionne ligne à ligne. On est bien forcé de parser au moins une fois le fichier jusqu'au bout pour identifier la ligne ou on veut intervenir.
                      Dans ton cas, plusieurs solutions :
                      - identifier le numéro de ligne du #endif qui t'intéresse (par exemple avec grep -n) et insérer ensuite ton accolade fermante avec une combinaison de head et tail
                      - compter le nombre d'occurences de #endif, et transmettre cette info à sed pour qu'il n'intervienne que sur cette occurence du motif. Je te laisse explorer un peu la doc de sed / grep.
                      Je te renvoie à l'excellent lien du commentaire http://linuxfr.org/comments/868660.html#868660

                      "Sinon tu es un chef !!"
                      merci :)
                      au bout de quelques années d'utilisation intensive, on finit par apprendre 2/3 trucs, surtout quand on aime ça ;)

Suivre le flux des commentaires

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