Forum Programmation.shell Recherche de chaine codées en dur ...

Posté par  .
Étiquettes : aucune
0
23
mar.
2006
Salut la compagnie,

J'aurais besoin d'un coup de main pour extraire d'une arborescence
de fichiers source toutes les chaines de caratères codées en dur.
Sachant que les chaines de caractères commencent par un
double-quote " et finissent par le même caractères.

Et je voudrais aussi ne pas prendre en compte les chaines de traces
du type Tracer_Message("Message de trace")
et afficher la ligne et le fichier dans lequel la chaine a été trouvée !!

Merci pour votre aide !

boro.
  • # deja pour commencer ....

    Posté par  . Évalué à 4.

    extraire d'une arborescence de fichiers source
    find

    afficher la ligne et le fichier dans lequel la chaine a été trouvée !!


    find . -exec awk '/".+"/{
    if (match($0,/Tracer_Message/)==0) {
    printf ("fichier %s ligne %s %s \n",FILENAME,NR,$0)
    }
    }' {} \;


    A adapter pour certains cas tordus (chaines dans un commentaires, etc ..).
  • # find, grep, cut ... kit de survie sous Unix.

    Posté par  . Évalué à 5.

    À l'arrache, ceci devrait approcher ce que tu veux faire :

    find ~ -name '*.c' -exec grep -v "Tracer_Message" {} \; | grep "^.*\".*\".*" | sed -e 's/^.*\(".*"\).*$/\1/g'
  • # Grep tout seul, c'est trop simple ?

    Posté par  . Évalué à 4.

    grep -rn "\".*\"" * | grep -v Tracer_Message

    -r : récursif
    -n : numéros de lignes.
  • # Cool !

    Posté par  . Évalué à 1.

    Merci pour vos deux solutions : elles marchent très bien,
    le newbie que je suis est impressionné.
    Par contre, dans un cas (totof) je trouve le nom du fichier et le numéro de ligne,
    mais pas la chaine cherchée elle-même.
    Dans l'autre cas (Robin), je trouve la chaine elle-même mais pas fichier et numéro de ligne !!!
    Messieurs ... ;)

    Et au passage, y a-t-il un moyen de traiter des syntaxes avec retour à la ligne
    du style

    string = "une chaine longue qu'il a fallut coupé pour des \
    raisons qui m'échappent"
    • [^] # Re: Cool !

      Posté par  . Évalué à 3.

      Peux tu me donner deux ou trois exemples de chaines a chercher, ainsi qu'un extrait de l'affichage que tu as?

      J'ai testé ici ça a l'air de marcher, mais je suis sous AIX.
    • [^] # Re: Cool !

      Posté par  . Évalué à 2.

      Tiens essaye ça pour les lignes tronquées:



      find . -exec awk '

      {LineNumber=NR }
      /\\$/ {
      getline LINE
      $0=LINE $0 "\n" LINE
      print LINE
      }
      /".+"/{
      if (match(Line,/Tracer_Message/)==0) {
      printf ("fichier %s ligne %s %s \n",FILENAME,LineNumber,$0)
      }
      }' {} \;



      Par contre je ne vois toujours pas pourquoi chez toi il n'affiche pas la ligne. T'as bien mis le $0 ?
      • [^] # Re: Cool !

        Posté par  . Évalué à 2.

        une petite erreur de ma part: il faut remplacer "/".+"/{
        " par "/".*"/{" ou le script ne détecte pas les chaines de type ""
        (chaines vides).
        • [^] # Re: Cool !

          Posté par  . Évalué à 1.

          OK , je teste à l'occasion car il semble que le cas
          réel rencontré soit encore plus biscornu que ça.
          Pour le moment, je lance ça :

          find . \( -name '*.cpp' -o -name '*.h' -o -name '*.bas' \) -exec awk '/".+"/{
          if (match($0,/#include/)==0 && match($0,/m_pQuery <</)==0 && match($0,/", "/)==0 && match($0,/OutputDebugString/)==0) {
          printf ("fichier %s ligne %s %s \n",FILENAME,NR,$0)
          }
          }' {} \; > chaines.txt

          mais je ne maitrise pas trop les clauses "ou".
          Je suis sur que l'on peut faire mieux ...

          Qu'en pensez-vous?

          boro
          • [^] # Re: Cool !

            Posté par  . Évalué à 2.

            Tu ne traites toujours pas le cas des chaines sur deux lignes ....
            Sinon un truc du style :

            if (match($0,/#include|m_pQuery<<|", "|OutputDebugString/==0) {
            [ SNIP]

            Si ca marche pas tu met chaque chaine recherchee entre parenthes :

            if (match($0,/(#include)|(m_pQuery<<)| [SNIP]

            Pour le coté biscornu je veux bien le croire, je me suis déjà tapé ce genre de travail. A l'époque j'avais utilisé Perl. J'ai laissé tomber en cours de route: trop de cas particuliers, pas le temps de développer un truc qui tient la route.
            j'ai résolu les cas les plus simples en auto et les plus tordus à la main.

            N'oublie pas de remplacer mon "+" par un "*" dans la recherge de regexp sinon tu ne detecte pas les chaines vides.
            • [^] # Re: Cool !

              Posté par  . Évalué à 1.

              Ok totof,

              bon, dans tout ça, j'en suis encore à essayer d'afficher à la fois la chaine originale ET le pattern trouvé dans la chaine.
              D'ailleurs au passage, il se peut qu'il y ait 2 ou 3 occurences
              du patterne dans la chaine ...

              Donc j'essaie de mettre ça dans un sed mais je perds le nom du fichier,
              le numéro de ligne ainsi que la ligne elle-même ...



              find . -exec awk '/".+"/{
              if (match($0,/Tracer_Message/)==0) {
              printf ("fichier %s ligne %s %s \n",FILENAME,NR,$0)
              }
              }' {} \; | sed -e 's/^.*\(".*"\).*$/\1/g'



              Voila ou j'en suis pour le moment.
              Ensuite, effectivement, traiter les multi lignes et, et, et
              passer encore du sed pour remplacer les formattage %d
              et autres par du %s.
              • [^] # Re: Cool !

                Posté par  . Évalué à 2.

                Normalement tu n'as pas besoin du sed pour afficher la ligne étant donné que le $0 est dans le printf et qu'il t'affiche la ligne complete.Essae de remplacer le printf complet par printf ("%s\n", $0").
                Tu vire le sed, et tu vois s'il t'affiche la ligne.
                • [^] # Re: Cool !

                  Posté par  . Évalué à 2.

                  Voila le résultat final :


                  find . -name *.cpp -exec awk -F\" '/"...*"/{
                  if (match($0,/Tracer_Message/)==0) {
                  printf ("%s;%s;%s;%s\n",FILENAME,NR,$0,$2)
                  }
                  }' {} \; > extraire_chaines.txt


                  Ruse pour afficher le champ seulement (pas la ligne complète):
                  je mets simplement le séparateur de champ à -F"
                  et j'affiche le deuxième champ.
                  Cela me permet théoriquement de traiter le cas ou il y a plusieurs
                  champs sur la même ligne.

                  ;)
                  • [^] # Re: Cool !

                    Posté par  . Évalué à 2.

                    Merci d'avoir posté le résultat final. C'est bon a savoir.

Suivre le flux des commentaires

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