IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation et administration système Perl Discussion :

Problème de regexp


Sujet :

Programmation et administration système Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Par défaut Problème de regexp
    Bonjour à tous,


    Je vous explique d'abord ce que je cherche à faire.

    Voici un fichier dont le contenu est:

    [ticket 1]
    xxxxxxxxxxxxx
    zzzzzzzzzzzzzz
    rrrrrrrrrrrrrrrrrCHAINE_RECHERCHErrrr
    tttttttttttttttttttt
    [ticket 2]
    fffffffffffffffffffffff
    bbbbbbbbbbbb[0]bbbb
    ccccccccc[1]ccccccccccccCHAINE_RECHERCHE
    rrrrrrrrrrrrrrrrrrrrrrrrrrr[2]rrrrrrrrr
    [ticket 3]
    ddddddddddddd
    zzzzzzz
    [ticket 4]
    cccccc
    tttttttttttttt
    ooooooooCHAINE_RECHERCHE
    ppppppppp


    Mon objectif en perl est de retourner le contenu des tickets contenant CHAINE_RECHERCHE, donc le resultat sera:

    [ticket 1]
    xxxxxxxxxxxxx
    zzzzzzzzzzzzzz
    rrrrrrrrrrrrrrrrrCHAINE_RECHERCHErrrr
    tttttttttttttttttttt
    [ticket 2]
    fffffffffffffffffffffff
    bbbbbbbbbbbb[0]bbbb
    ccccccccc[1]ccccccccccccCHAINE_RECHERCHE
    rrrrrrrrrrrrrrrrrrrrrrrrrrr[2]rrrrrrrrr
    [ticket 4]
    cccccc
    tttttttttttttt
    ooooooooCHAINE_RECHERCHE
    ppppppppp


    Est ce que quelqu'un peut me donner un coup de main svp ?


    Merci d'avance!

  2. #2
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    L'algorithme générique concernant le traitement de tels blocs est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    my @bloc = ();
    while (<STDIN>) {
      if (/début bloc/) {
        traiter(@bloc) if @bloc;
        @bloc = ();
      }
      push @bloc, $_;
    }
    traiter(@bloc) if @bloc;
     
    # Traitement du bloc
    sub traiter {
      my @bloc = @_;
     
      print @bloc if grep /CHAINE_RECHERCHE/, @bloc;
    }
    en remplaçant /début bloc/ par la regexp permettant d'identifier le début d'un bloc (ici, quelque chose comme /^\[[^\]]\]/).

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    L'algorithme générique concernant le traitement de tels blocs est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    my @bloc = ();
    while (<STDIN>) {
      if (/début bloc/) {
        traiter(@bloc) if @bloc;
        @bloc = ();
      }
      push @bloc, $_;
    }
    traiter(@bloc) if @bloc;
     
    # Traitement du bloc
    sub traiter {
      my @bloc = @_;
     
      print @bloc if grep /CHAINE_RECHERCHE/, @bloc;
    }
    en remplaçant /début bloc/ par la regexp permettant d'identifier le début d'un bloc (ici, quelque chose comme /^\[[^\]]\]/).
    Salut Philou, merci pour ton retour!
    EN fait l'algo je l'ai et il fonctionne (j'aurais du préciser), sauf que j'ai une quantité considérable de ticket à traiter (environ 1000000) donc je voudrais passer par un regexp qui me fait mon traitement en une fois, pour optimiser les perf.

  4. #4
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Peux-tu montrer ton algorithme (ton script ou la partie qui traite les tickets), car j'ai du mal à imaginer qu'une regexp seule puisse améliorer un algorithme (par ailleurs, l'algo que je propose est, me semble-t-il, parmi les plus performants qui puissent être) ?

    Si tu veux améliorer les performances, il faut peut-être justement abandonner les regexp au profit de la recherche de texte (avec index par exemple).

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Peux-tu montrer ton algorithme (ton script ou la partie qui traite les tickets), car j'ai du mal à imaginer qu'une regexp seule puisse améliorer un algorithme (par ailleurs, l'algo que je propose est, me semble-t-il, parmi les plus performants qui puissent être) ?

    Si tu veux améliorer les performances, il faut peut-être justement abandonner les regexp au profit de la recherche de texte (avec index par exemple).
    Voici mon code commenté qui fonctionne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #variable globale
    $extension="ascii";
     
    find(\&FindFormats,"@ARGV[1]"); #le find appel la fonction FindFormats à partir de l'arborescence passé en paramètre, autant de fois qu'il y a de fichiers trouves
     
    sub FindFormats {
    	if (-f $File::Find::name) {
    		$cheminfichier=$_;
     
    		#decodage du ticket en ascii
    		decode_TT($cheminfichier);
     
    		open(FH,"$cheminfichier.$extension") or die "ouverture NOK du fichier $_.$extension : $!";
    		while(<FH>) { #tant qu'on a pas atteint la fin du fichier ascii
    			chomp; # supprime le caractere de fin de ligne
     
    			# si la ligne commence par [ticket \d+] 
    			# on vérifie dans ce bloc que le ticket qui vient d'être parcouru matche ou ne matche pas
    			# si il match, on affiche le ticket parcouru
    			if ( /^\[ticket \d+\]/ ) { 
    				# si $match defini et =!0 
    				# on affiche l'integralite du ticket qui repond au critere SINON je le supprime du tableau de hash
    				$match and print "$h{$c}" or delete($h{$c}); 
     
    				# on a trouve un nouveau debut de ticket
    				# on reinitialise le flag $match à 0 et on incremente le compteur de ticket trouve
    				$c++;$match=0; 
    			}
    			$h{$c}.="$_\n";	#on concatene la ligne lue
    			m/$ARGV[0]/ and $match++; #Si la chaine est trouvée, on flag avec match
    		}
    		$match and $match=0,print "$h{$c}"; #Si le dernier ticket du fichier a matché, on reinitalise le flag match et on print le dernier ticket trouve
    		close(FH);
    		#Suppression du fichier ascii après traitement
    		unlink "$cheminfichier.$extension";
    	}
    }

    Et voici le code qui me sert de test pour la regexp que j'aimerais faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $S=qq{[ticket 1]
    ticket1
    ticket1SearchedStringticket1
    ticket1
    [ticket 2]
    ticket2
    ticket2
    ticket2
    ticket2.[0].SearchedString;values
    [ticket 3]
    ticket3
    SearchedStringticket3ticket3
    ticket3
    };
    map{$c++;s/\[ticket \d+/\[ticket $c/;print} $S=~/^\[ticket \d+\][^\[]+SearchedString[^\[]*/msg;
    Cette regexp ne fonctionne pas pour les ticket contenant des ligne de type
    aaaaaaa[0]zzzzzzCHAINE_RECHERCHErrrrrrrr

  6. #6
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Si j'ai bien compris, ce que tu cherches à faire, c'est écrire une regexp qui capture jusqu'à 10000000 de tickets en matchant une variable qui contiendrait la totalité du message, et ceci, pour optimiser les performances ?
    Outre le fait qu'une telle expression régulière, basée sur une chaine multiligne, sera peut-être difficile à trouver, je pense personnellement que ce serait une contre-performance, en terme d'occupation mémoire, et en terme de temps de traitement.

    Sinon, pour ton exemple précédent, voici une façon de matcher qui fonctionne. Elle se base sur un principe différent : séparer la chaine originale en tickets, dont on sélectionne seulement ceux qui contiennent SearchedString (le même principe que l'algorithme que j'ai proposé plus haut, ou que ton algorithme original) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $S=qq{[ticket 1]
    ticket1
    ticket1SearchedStringticket1
    ticket1
    [ticket 2]
    ticket2
    ticket2
    ticket2
    ticket2.[0].SearchedString;values
    [ticket 3]
    ticket3
    SearchedStringticket3ticket3
    ticket3
    };
    map{$c++;s/\[ticket \d+/\[ticket $c/;print} grep /SearchedString/, $S=~/(\[ticket \d+\].*?)(?=\[ticket |$)/sg;
    Mais je suis convaincu que les performances sur de gros fichiers seront moins bonnes que l'algorithme itératif.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. URL Rewriting problème de regexp ?
    Par pierrickg dans le forum Apache
    Réponses: 2
    Dernier message: 10/07/2007, 13h35
  2. Un petit problème de regExp
    Par guidav dans le forum VBA Access
    Réponses: 4
    Dernier message: 31/05/2007, 17h36
  3. Probléme de regexp
    Par moook dans le forum Langage
    Réponses: 4
    Dernier message: 17/04/2007, 11h17
  4. Problème de regexp
    Par vodevil dans le forum Langage
    Réponses: 1
    Dernier message: 08/12/2006, 21h28
  5. Gros problème avec regexp
    Par dmbsys dans le forum ASP
    Réponses: 6
    Dernier message: 29/04/2006, 16h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo