Forum Programmation.perl grep multi-ligne

Posté par  (site web personnel) .
Étiquettes : aucune
0
26
juil.
2006
Bonjour, j'essaie depuis deux jours d'effectuer un grep multiligne sur un certains nombre de fichier sources pour en extraîres les commentaires.

Je cherche à sélectionner des patterns de ce genre :
- to_ulongint:ULONGINT <-
( //? {self >=0};
//? {self <=# (ULONGINT.maximum)};


au milieu de //
// Conversion format with test.
//

- to_ulongint:ULONGINT <-
( //? {self >=0};
//? {self <=# (ULONGINT.maximum)};
to_raw_ulongint
);


J'ai donc créé l'expression suivante :
^\s*-([.]*)<-\s*\(*\s*//(.*)

Lorsque je la teste avec un outil comme regexp-coach, je constate qu'en gros elle me sélectionne ce que je veux.

Mais voilà, problème, je n'arrive pas à la faire marcher avec perl. Principalement, à mon avis, car il s'agit de détecter des pattern de plusieurs lignes.

Lorsque je tente une commande du genre
perl -n -0777e 'print if /^\s*-[^<]*<-\s*\(*\s*(?:\/\/.*$\s*)+/mx' numeric.li

Il m'affiche tout le fichier. J'ai bien essayé des configurations différentes, genre tester -n ou -p, mettre ou pas -0777 avec les modificateurs m et x, cela dans toutes les combinaisons possibles. Mais je n'obtiens rien que soit une ligne vide, soit l'intégralité du fichier.

Encore une exemple pour la route. Je met en italique ce que l'utilitaire regexp-coach (utilitaire permettant de tester une regexp au format perl, et surlignant ce qui matche dans la chaîne cible



- to_hexadecimal_format s:INTEGER :STRING <-
// Convert the hexadecimal view of `self' into a new allocated
// STRING. For example, if `self' is -1 the new STRING is
// "FFFFFFFF" on a 32 bit machine.
// Note: see also `to_hexadecimal_in' to save memory.
(
+ result:STRING;

result := STRING.create 8;
to_hexadecimal_in result format s;
result
);

- to_hexadecimal_in buffer:STRING <-
// Append in `buffer' the equivalent of `to_hexadecimal'. No new STRING
// creation during the process.
( + val:SELF;
+ i,old_count:INTEGER;
? {buffer!=NULL};

(self==0).if {
buffer.extend '0';
} else {
i := buffer.count + 1;
val := self;
{val != 0}.while_do { //JBJB
buffer.extend ((val & 15).hexadecimal_digit);
val := val >> 4;
};
old_count := buffer.count;
{i >= old_count}.until_do {
buffer.swap i with old_count;
old_count := old_count - 1;
i := i + 1;
};
};
);
  • # Ouuups

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

    Je me suis trompé de regexp
    La bonne est :
    ^\s*-[^<]*<-\s*\(*\s*(?:\/\/.*$\s*)+

    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

  • # Slurp mode

    Posté par  . Évalué à 3.

    Tu veux probablement activer le "slurp mode", c'est-à-dire faire fonctionner perl sur le fichier entier et non pas ligne par ligne, en désactivant le séparateur de lignes avec undef $/;

    (man perlvar, ou http://perldoc.perl.org/perlvar.html )
    • [^] # Re: Slurp mode

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

      J'ai donc fait le script suivant

      #!/bin/perl
      undef $/;

      while ($myline = )
      {
      print "coucou";
      if ($myline =~ /^\s*-[^<]*<-\s*\(*\s*(?:\/\/.*$\s*)+/)
      {
      print 'trouvé'."\n";
      print 'Méthode : '.$1.'Commentaire : '.$2,"\n";
      }

      }


      Il m'affiche "coucou" une fois et puis plus rien.

      Je viens de tester un truc intéressant : j'ai supprimé les première lignes du fichier, et fais commencer le fichier à une ligne qui matche.

      Et là, Il la trouve effectivement...

      Il faudrait donc que je lui fasse tester le fichier entier n fois (n = nombre de lignes) en supprimant en supprimant la ième ligne à la ième itération..

      « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

      • [^] # Re: Slurp mode

        Posté par  . Évalué à 3.

        En fait il faut comprendre que dans ce mode, il n'y a effectivement qu'une seule ligne (tres longue). Ton while() ne fait qu'un tour; de même, dans ta regexp, le "^" de début de ligne est aussi un début de fichier.


        Je connais tres peu perl en fait, mais un exemple de script qui traine chez moi itère sur le fichier en capturant les morceaux de fichiers autour de la regexp de cette façon:


        # Ads deleter in HTML
        undef $/; # enable "slurp" mode
        $Tstart ="<!--Start of Ad -->";
        $Tend ="<!--End of Ad-->";
        while (<>) {
        while ( /(.*)$Tstart.*?$Tend(.*)/s ){ $_= "$1$2";}
        print "$_";
        }


        Et pour matcher des frontières de "vraie ligne" sans ^ ni $, on peut utiliser \n (c'est un peu crade...)

        Si un expert en perl passe ici et veut bien prendre le relai...
  • # Pattern de plusieurs lignes

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

    Si tu veux faire une regex multi-lignes, il faut rajouter le modifieur 's'

    Donc quelque chose comma ça :
    perl -n -0777e 'print if /^\s*-[^<]*<-\s*\(*\s*(?:\/\/.*$\s*)+/mxs' numeric.li

Suivre le flux des commentaires

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