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

Langage Perl Discussion :

parsing de fichier texte log


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 92
    Par défaut parsing de fichier texte log
    Bonjour,

    Je souhaiterais faire un parsing de fichier texte, log.
    Le fichier est composé de plusieurs ligne qui se génère automatiquement lorsque l' on utilise un logiciel

    le fichier est de la sorte
    DATE | TIME | PID.TID | LEVEL | < Class::Method > | Message
    exemple
    06/10/2014 | 15:34:17.765 | 03488.05340 | INFO | <CsterEOS3DApp::InitInstance > | Starting sterEOS 3D 1.7.2.8085
    06/10/2014 | 15:34:21.671 | 03488.05340 | INFO | <CLicenseKeyManager::IsLicenseKeyValid > | Valid license key.
    06/10/2014 | 15:34:21.671 | 03488.05340 | WARNING | <CsterEOS3DApp::SetParameters > | Unknown option name. Starting in standard mode
    06/10/2014 | 15:34:21.671 | 03488.05340 | WARNING | <CRegistry::ReadString > | Registry key not found: HipPlanning. Using default value:
    06/10/2014 | 15:34:26.984 | 03488.05340 | INFO | <CsterEOS3DDoc::OnOpenDocument > | Opening EOS 2D images. Patient ID: 0011
    06/10/2014 | 15:34:27.468 | 03488.05340 | WARNING | <CStudyStep::OnInitDialog > | hipEOS option not available
    06/10/2014 | 15:34:27.468 | 03488.05340 | INFO | <CStudyState::raffraichirEtat > | Study

    Je souhaiterais par exemple pouvoir voir le temps d'exécution entre différentes étapes, voir le nombres de fois que la même méthode ou classe apparaît.
    J'ai essayé de trouver le moyen le plus facile de réaliser ceci sur internet mais entre logparser/log parser studio, la programmation en perl ou c++, je ne sais pas quoi faire.

    Merci de vos conseils

  2. #2
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    Citation Envoyé par shalfat Voir le message
    Je souhaiterais par exemple pouvoir voir le temps d'exécution entre différentes étapes
    pour le coup j'aurais tendance à y aller en Perl, parceque je vois pas trop comment faire plus simple avec awk par exemple

    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
    #!/usr/bin/env perl
     
    use strict;
    use warnings;
    use Time::Local qw(timelocal);
    use Time::HiRes qw(tv_interval);
     
    my $prev;
    while (<>) {
            my $line = $_;
            if ($line =~ /^DATE/) { next; }
            my @F = split(/[\s]+/, $line);
            my ($month,$day,$year) = $F[0] =~ m{^(..)/(..)/(.{4})$};
            my ($hour,$mins,$sec,$frac) = $F[2] =~ m{^(..):(..):(..)\.(.{3})$};
            my $time = [timelocal($sec,$mins,$hour,$day,$month,$year) . "." . $frac];
            $prev = $time unless defined($prev);
            $F[2] = sprintf ("%.3f", tv_interval($prev, $time));
            $prev = $time;
            print join(" ", @F)."\n";
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ ./parser.pl < fichier
    06/10/2014 | 0.000 | 03488.05340 | INFO | <CsterEOS3DApp::InitInstance > | Starting sterEOS 3D 1.7.2.8085
    06/10/2014 | 3.906 | 03488.05340 | INFO | <CLicenseKeyManager::IsLicenseKeyValid > | Valid license key.
    06/10/2014 | 0.000 | 03488.05340 | WARNING | <CsterEOS3DApp::SetParameters > | Unknown option name. Starting in standard mode
    06/10/2014 | 0.000 | 03488.05340 | WARNING | <CRegistry::ReadString > | Registry key not found: HipPlanning. Using default value:
    06/10/2014 | 5.313 | 03488.05340 | INFO | <CsterEOS3DDoc::OnOpenDocument > | Opening EOS 2D images. Patient ID: 0011
    06/10/2014 | 0.484 | 03488.05340 | WARNING | <CStudyStep::OnInitDialog > | hipEOS option not available
    06/10/2014 | 0.000 | 03488.05340 | INFO | <CStudyState::raffraichirEtat > | Study
    voir le nombres de fois que la même méthode ou classe apparaît.
    là en revanche on doit pouvoir faire plus simple, du genre grep -Po "<.+>" fichier | sort | uniq -c ou grep -Po "<.+::" fichier | sort | uniq -c

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 92
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    salut,


    pour le coup j'aurais tendance à y aller en Perl, parceque je vois pas trop comment faire plus simple avec awk par exemple
    Merci de ton conseil BufferBob.

    Je vais donc essayer de faire un programme avec Perl, même si je n'ai aucune base dans ce langage de programmation.

    J'avais entendu parler de AWK, mais je n'ai pas réussi à comprendre comment l'installer sous windows. Pense tu qu'avec AWk il me serait plus simple de réaliser ce que je dois faire ?

    Car ensuite en réalité j'aurais plusieurs chose à parser et même par la suite si possiblité faire des graphiques avec les données obtenu à partir des fichier d'entrées.

    Merci bien.

  4. #4
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par shalfat Voir le message

    J'avais entendu parler de AWK, mais je n'ai pas réussi à comprendre comment l'installer sous windows. Pense tu qu'avec AWk il me serait plus simple de réaliser ce que je dois faire ?

    Non, awk est très bien pour des tâches textuelles simples, Perl est bien mieux dès que ça devient un peu plus compliqué. Là, je te conseille aussi du Perl.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 92
    Par défaut
    Citation Envoyé par BufferBob Voir le message

    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
    #!/usr/bin/env perl
     
    use strict;
    use warnings;
    use Time::Local qw(timelocal);
    use Time::HiRes qw(tv_interval);
     
    my $prev;
    while (<>) {
            my $line = $_;
            if ($line =~ /^DATE/) { next; }
            my @F = split(/[\s]+/, $line);
            my ($month,$day,$year) = $F[0] =~ m{^(..)/(..)/(.{4})$};
            my ($hour,$mins,$sec,$frac) = $F[2] =~ m{^(..):(..):(..)\.(.{3})$};
            my $time = [timelocal($sec,$mins,$hour,$day,$month,$year) . "." . $frac];
            $prev = $time unless defined($prev);
            $F[2] = sprintf ("%.3f", tv_interval($prev, $time));
            $prev = $time;
            print join(" ", @F)."\n";
    }

    J'ai commencé à rédiger mon programme, j'y vais progressivement pour faire un bon travail.
    Mais BufferBob, je ne comprend pas entièrement le programme que tu à écris, pourrais tu m’éclaircir sur ces lignes de codes ?
    my @F = split(/[\s]+/, $line);
    my ($month,$day,$year) = $F[0] =~ m{^(..)/(..)/(.{4})$};
    my ($hour,$mins,$sec,$frac) = $F[2] =~ m{^(..)..)..)\.(.{3})$};
    my $time = [timelocal($sec,$mins,$hour,$day,$month,$year) . "." . $frac];
    $prev = $time unless defined($prev);
    $F[2] = sprintf ("%.3f", tv_interval($prev, $time));

    Merci pour ton aide.

  6. #6
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my @F = split(/[\s]+/, $line); # splitte la ligne sur des espaces et mets les champs obtenus dans le tableau @F
    my ($month,$day,$year) = $F[0] =~ m{^(..)/(..)/(.{4})$}; # expression régulière cherchant 2 chiffres, / 2 chiffres / 4 chiffres dans le premier champ de @F pour récupérer le mois, le jour et l'année dans trois variables
    my ($hour,$mins,$sec,$frac) = $F[2] =~ m{^(..)..)..)\.(.{3})$}; # même type de chose pour heures, minutes secondes, fraction de seconde
    # etc.

  7. #7
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    Citation Envoyé par shalfat Voir le message
    Pense tu qu'avec AWk il me serait plus simple de réaliser ce que je dois faire ?
    Citation Envoyé par Lolo78 Voir le message
    Non, awk est très bien pour des tâches textuelles simples, Perl est bien mieux dès que ça devient un peu plus compliqué. Là, je te conseille aussi du Perl.
    pour préciser un peu plus, le propos du script ici, c'est à dire l'action qui fait office de "pivot" central, c'est de calculer la différence entre deux dates formatée à chaque fois qu'on lit une ligne (la date/l'heure de la ligne en cours moins la date/l'heure de la ligne précédente), et qui plus est avec une précision de l'ordre du millième de seconde.

    on doit pouvoir le faire en awk, mais pour le coup c'est bien plus simple en perl grâce à la fonction Time::HiRes::tv_interval(), évidement c'est le genre de considération que l'on ne peut avoir qu'en connaissant déjà un peu les possibilités et les limites des deux langages
    donc pour répondre à la question, le plus "simple" c'est le script que tu fais dans le langage que tu connais le mieux, le plus concis en revanche dans le cas présent ce sera probablement en Perl (même si mon script n'est pas forcément un modèle de concision pour le coup )

    Citation Envoyé par shalfat Voir le message
    je ne comprend pas entièrement le programme que tu à écris
    j'avoue j'aurais pu (du) commenter un peu, Lolo78 a en partie répondu et assez intuitivement aussi le nom des variables aurait pu te donner une idée de ce que fait chaque ligne

    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
    while (<>) {
            # on lit ligne après ligne depuis l'entrée standard
            my $line = $_;
     
            # si c'est la premiere ligne, on la passe, il n'y a rien à faire dessus
            if ($line =~ /^DATE/) { next; }
     
            # sinon on commence par decouper la ligne en plusieurs parties (séparées par des espaces)
            my @F = split(/[\s]+/, $line);
     
            # on récupère jour, mois, année en appliquant une regex sur la partie 0 (la première partie de la ligne, la date donc)
            # comme dit Lolo78 on cherche quelque chose qui ressemble à "2 chiffres/2 chiffres/4 chiffres"
            my ($month,$day,$year) = $F[0] =~ m{^(..)/(..)/(.{4})$};
     
            # dans le meme ordre d'idée on récupère heure, minutes, secondes, millièmes à partir de la partie 2 (troisième partie donc, l'heure et les millièmes de seconde)
            # là encore on cherche un pattern du genre "2 chiffres:2chiffres:2chiffres.3chiffres"
            my ($hour,$mins,$sec,$frac) = $F[2] =~ m{^(..):(..):(..)\.(.{3})$};
     
            # on crée un timestamp "haute précision" pour donner à manger à tv_interval()
            my $time = [timelocal($sec,$mins,$hour,$day,$month,$year) . "." . $frac];
     
            # ici une astuce dégueu pour que la 1ere mesure vaille 0.000, en effet vu qu'on effectue une soustraction plus bas,
            # si $prev valait 0, la première valeur serait le timestamp correspondant à "06/10/2014 15:34:17.765", une valeur très grande et fausse qui plus est
            # donc on choisit de dire "si la variable $prev n'a pas encore de valeur, alors on lui affecte celle de $time", la soustraction donnera donc 0.000
            $prev = $time unless defined($prev);
     
            # enfin on substitue directement la partie 2 de la ligne par notre valeur
            $F[2] = sprintf ("%.3f", tv_interval($prev, $time));
            $prev = $time; # on oublie pas d'affecter $prev, qui au prochain tour de boucle aura la valeur de $time du tour précédent
     
            # et on affiche toutes les parties de la ligne, avec un espace pour les séparer à chaque fois
            print join(" ", @F)."\n";
    }

  8. #8
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 92
    Par défaut Parsing de fichier log en perl, extraction de l'heure
    Citation Envoyé par BufferBob Voir le message
    salut,
    Merci BufferBob et Lolo.

    Rebonjour, j'ai écrit un programme qui extrait l'heure des lignes d'un fichier et qui calcule la difference entre deux heures. le programme est presque fonctionel mais j'aimerai savoir si vous avez une solution à mon problème

    voici le fichier texte que je lis en entrée

    LOG de début de l'étude de la colonne vertébrale:
    06/10/2014 | 11:09:21.015 | 05276.03080 | INFO | <CStudyState::Leave > | Spine study

    LOG de fin de l'étude de la colonne vertébrale:
    06/10/2014 | 11:53:16.265 | 05276.03080 | INFO | <CSpineWorkflowCompleteState::raffraichirEtat > | Spine workflow complete

    LOG de fin de l'étude de la colonne vertébrale:
    06/10/2014 | 11:54:09.218 | 05276.03080 | INFO | <CSpineWorkflowCompleteState::raffraichirEtat > | Spine workflow complete

    LOG de fin de l'étude de la colonne vertébrale:
    06/10/2014 | 11:54:37.578 | 05276.03080 | INFO | <CSpineWorkflowCompleteState::raffraichirEtat > | Spine workflow complete



    Le résultat que j'obtient sur un fichier est le suivant

    0
    -669.35025
    -669.35025
    -669.35025
    43.9208333333333
    43.9208333333333
    43.9208333333333
    44.8033833333334
    44.8033833333334
    44.8033833333334
    45.2760500000001
    45.2760500000001


    Mais je voudrais obtenir uniquement ce résultat et je ne vois pas où est l'erreur.

    43.9208333333333

    44.8033833333334

    45.2760500000001


    Voici mon code

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    use strict;
    use warnings;
    use Data::Dumper;
    use Carp;
     
    sub lire_fichier($)
    {
    my $fichier = shift;
    open (my $fh_src, '<', $fichier) or die "Impossible d'ouvrir le fichier en lecture";
    my $final;
    my $start_time;
    my $end_time;
     
    while (my $ligne = <$fh_src>) 
    {
    	my($heure, $minute, $seconde, $milliseconde)=$ligne =~ /(\d\d):(\d\d):(\d\d).(\d\d\d)/;
     
    	if ($ligne=~/Spine study/)
    	{
    		my($heure, $minute, $seconde, $milliseconde)=$ligne =~ /(\d\d):(\d\d):(\d\d).(\d\d\d)/;
    		$start_time = (((($heure * 60)+ $minute) *60 + ($seconde+($milliseconde/1000)))/60);
    	}
     
    	elsif($ligne=~ /Spine workflow complete/)
    	{
    		my($heure, $minute, $seconde, $milliseconde)=$ligne =~ /(\d\d):(\d\d):(\d\d).(\d\d\d)/;
    		$end_time = (((($heure * 60)+ $minute) *60 + ($seconde+($milliseconde/1000)))/60);
    	}
     
    my @res = ($end_time) - ($start_time);
     
    push @$final, @res;
     
    }
    return $final;
    }
     
    sub imprimer_fichier ($$)
    {
    	my $fichier = shift;
    	my $final = shift;
    	open (my $fh_dst, '>', $fichier) or die "Impossible d'ouvrir le fichier en ecriture";
    	print $fh_dst join ("\n",@$final);
    	close $fh_dst;
    	return 1;
    }
     
    my $fichier_src = "C:\\Documents and Settings\\stage\\Mes documents\\Stage_gabriel\\FichierLog\\test2.txt";
    my $fichier_dst = "C:\\Documents and Settings\\stage\\Mes documents\\Stage_gabriel\\FichierLog\\temps.txt";
     
    my $final = lire_fichier($fichier_src);
     
    my $res = imprimer_fichier($fichier_dst, $final);
     
    <>;
    Merci de votre aide

Discussions similaires

  1. Parsing de fichier texte
    Par gege2009 dans le forum C++
    Réponses: 10
    Dernier message: 22/12/2010, 14h32
  2. Parsing de fichiers texte
    Par ChristopheD dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 29/07/2010, 02h50
  3. parsing de fichier texte
    Par robert_trudel dans le forum Access
    Réponses: 4
    Dernier message: 03/06/2006, 17h45
  4. Parser de fichier textes >> Logs Apache
    Par gregb34 dans le forum Langage
    Réponses: 2
    Dernier message: 17/02/2006, 18h34
  5. [MFC]creation fichier text / log
    Par tus01 dans le forum MFC
    Réponses: 4
    Dernier message: 04/01/2006, 19h22

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