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

  1. #1
    Futur Membre du Club
    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
    Points : 8
    Points
    8
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    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 /^\[[^\]]\]/).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  3. #3
    Futur Membre du Club
    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
    Points : 8
    Points
    8
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    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).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  5. #5
    Futur Membre du Club
    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
    Points : 8
    Points
    8
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    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.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  7. #7
    Futur Membre du Club
    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
    Points : 8
    Points
    8
    Par défaut
    Merci pour le code
    Tu as effectivement bien cerné mon besoin

    Je ferai quelque test de volumétrie pour comparer!

  8. #8
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    Par défaut
    Peut-être devrais-tu profiler ton script avec des exemples de fichier pas trop gros (car le profilage rallonge considérablement le temps de traitement), afin d'identifier si la fonction decode_TT ne gagnerait pas à être optimisée ?

    Pour profiler

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perl -d:DProf script.pl && dprofpp
    (voir les options de dprofpp, notamment l'option -I, si besoin).
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

+ 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