[Perl] débutant chercher conseil

jojo -  
 jojo -
bonjour,
je suis complétement novice en programmation mais dans le cadre de mon travail j'ai besoin de manipuler des données dans des fichiers texte. Perl est bien adapté pour cela.
1ère Q: : que dois-je installé comme environnement perl ?
j'ai téléchargé activePerl mais j'ai des soucis avec l'archive récupérée. j'arrive pas à l'installer
2ème Q : mon besoin
je dois rechercher dans plusieurs fichiers dont le nom est différent
et par date (ex: 200612) et une chaîne de caractère s=1, s=2, s=3 etc... et compter le nombre de s=1, s=2 etc... et envoyer le résultat dans un fichier avec les infos
200612
s=1 xxx
s=2 xxx
etc...
merci pour vos conseils
jojo
Configuration: Windows XP
Internet Explorer 6.0

9 réponses

  1. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    d'abord on va traiter la 1ère question :-)

    depuis quel site tu as téléchargé ActivePerl?
    et comment tu te prends pour l'installation?
    0
    1. jojo
       
      bonjour,
      c'est règlé , j'ai téléchargé l'archive msi et l'installe est ok
      je suis presque prêt
      active perl et pspad installé
      merci
      jojo
      0
    2. jojo
       
      bonsoir,
      alors personne peut m'aider sur mon problème ?
      merci
      jojo
      0
  2. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    comme je ne connais pas le contenu de tes fichiers, j'ai imaginé cette situation (4 fichiers dans le répertoire /home/lami20j/jojo)
    la commande cat affiche le contenu de chaque fichier
    lami20j@debian:~$ cat jojo/200610
    s=1 s=2 s=3
        s=2 s=3
            s=3
    lami20j@debian:~$ cat jojo/200611
    s=1 s=2 s=3
    s=1 s=2 s=3
        s=2
    s=1 s=2
    
    lami20j@debian:~$ cat jojo/200612
    s=1 s=2 s=3
    s=1 s=2 s=3
    s=1 s=2 s=3
        s=2 s=3
    s=4 s=4 s=3
    
    lami20j@debian:~$ cat jojo/200701
    s=4 s=5 s=6
    s=1 s=2 s=3
        s=2 s=3
            $=3
    s=5 s=5 s=5
    s=5 s=5 s=5
    s=5 s=5 s=5
    
    Le script va créer un fichier que je l'ai appellé jojo_resultat
    Voici le script (je l'ai nommé jojo.pl)
    #!/usr/bin/perl
    #
    use warnings;use strict;
    use File::Basename;
    
    my (@fichiers,%h);
    my $rep="/home/lami20j/jojo";
    
    opendir (REP,$rep)
       or die "E/S : $!\n";
    
    open F_ECRIRE,">>jojo_resultat"
       or die "E/S : $!\n";
    
    while (defined (my $fic = readdir(REP))){
      push @fichiers,"$rep/$fic" unless $fic=~/^\./;
    }
    
    foreach my $fic(sort @fichiers){
      open F_LIRE,"$fic"
         or warn "E/S : $!\n";
      while(<F_LIRE>){
        map { $h{$_}++ } my @t=$_=~/(s=\d+)/g;
      }
      print F_ECRIRE basename($fic),"\n";
      print F_ECRIRE "$_ $h{$_}\n" foreach (sort keys %h);
      delete $h{$_} foreach (keys %h);
    }
    
    Et le résultat
    lami20j@debian:~$ perl jojo.pl
    lami20j@debian:~$ cat jojo_resultat
    200610
    s=1 1
    s=2 2
    s=3 3
    200611
    s=1 3
    s=2 4
    s=3 2
    200612
    s=1 3
    s=2 4
    s=3 5
    s=4 2
    200701
    s=1 1
    s=2 2
    s=3 2
    s=4 1
    s=5 10
    s=6 1
    
    0
    1. jojo
       
      bonjour,
      merci pour ta réponse, mais je comprend rien !
      les recherches à faire sont sur des fichiers de log et j'ai effectivement 4 fichiers mais qui peuvent être à cheval de date, voilà pourquoi il faudrait part exemple avant de lancer le script
      que je précise la date ex: année 2006 et mois 12
      est-ce que les constantes existes en perl ?
      maintenant à l'intérieur des fichiers, je peux trouver S=1 ou s=2 etc... qu'une fois part ligne, il faut donc rechercher cette chaîne dans toutes les lignes et compter pour l'écrire dans un fichier.
      qu'est-ce que c'est les use ?
      que veut dire @fichiers, %h c'est un tableau ? et %h
      je comprend pas le while et foreach
      merci bien je vois que tu maîtrise bien le sujet !
      jojo
      0
  3. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    j'aimerai bien savoir exactement ce que tu veux et si possible d'avoir un exemple de ce que contient tes fichiers (tu peux mettre sur cjoint.com)

    s=1 xxx

    que veux tu dire par xxx ?

    maintenant à l'intérieur des fichiers, je peux trouver S=1 ou s=2 etc... qu'une fois part ligne

    J'ai conçu le script d'une manière qu'il prendre en compte n'importe combien de couple par ligne , aucun, un ou plusieurs

    je n'aime pas etc.
    soit un peu plus précis.

    ce soir je n'ai pas le temps, on verra ça demain

    je vais t'expliquer ce que j'ai fait, mais je crois que tu dois commencer à lire un peu. tu peux commencer avec perlintro et https://perl.developpez.com/cours/
    0
    1. jojo
       
      bonsoir,
      xxx c'est le nombre de fois trouvé
      j'ai pas d'exemple chez moi, mais comme je l'ais dit c'est des fichiers de log pour être plus précis c'est une ligne par connexion
      dans cette ligne il faut que je recherche une chaîne s= qui peut avoir comme valeur 1, 2, 3, 4 ,
      et écrire le cumul dans un fichier résultat
      merci
      cdt
      jojo
      0
  4. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Re,

    c'est exactement ce que fait le script (ne te laisse pas piegé par l'exemple que je l'ai donné, ça marche aussi s'il y a un seul couple s=N )

    le résultat est écrit dans un seul fichier
    le script traite tous le fichiers de répertoire

    maintenant l'important c'est la sortie

    tu veux avoir en sortie combien de fichiers, un pour chaque fichier log ou un seule fichier avec le formant
    nom_fichier1
    s=1 xxx
    .
    .
    nom_fichier2
    s=1 xxx
    .
    .

    Tu veux traiter tous les fichiers de répertoire, ou un certain fichier à la demande?

    En fonctionne de tes réponses je peux améliorer le script.

    Je vais repondre à tes questions (c'est promis :-)), mais d'abord je dois savoir exactement ce que tu veux :-))
    0
    1. jojo
       
      bonsoir,
      après recherche dans les fichiers log j'ai besoin d'un seul fichier résultat avec
      s=1 xxx
      s=2 xxx
      et ainsi de suite
      cdt
      jojo
      0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    En fait tu veux un calcul total quelque soit le nombre de fichiers?

    par exemple

    dans fichier 1
    s=1
    s=2
    s=1
    .

    dans fichier 2

    s=1
    s=1
    s=2

    Le resultat

    s=1 4
    s=2 2

    c'est ça que tu veux?
    0
    1. jojo
       
      c'est ça
      merci
      0
      1. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571 > jojo
         
        Ok,

        je ferai ce soir les modifications et je vais te donner les explications nécessaires (algo et syntaxe de langage, en revanche ça ne sera pas un cours de Perl :-) pour ça il faut lire, et il y en a un peu :-))

        A ce soir
        0
  7. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    voilà le script (ce que tu vois en gras c'est le code, le reste se sont des commentaires, il faut les lire, c'est pour toi que je les ai écrit :-))
    #!/usr/bin/perl
    #
    =pod
    on utilise les pragma strict
    pour imposer une certaine discipline
    la déclaration de variables avec my
    dans notre cas
    
    on utilise le pragma warnings pour
    l'affichage des warnings
    ce qui peux nous aider pour corriger
    les erreurs
    =cut
    use warnings;use strict;
    
    =pod
    J'utilise 3 variables
    @fichiers - c'est un tableau
    les éléments du tableau peuvent être lus avec
    $fichiers[0]....$fichiers[n-1] - pour un tableau avec n éléments 
    
    %h - c'est un hash, ou hachage ou tableau associatif
    on préfére le plus court, donc hash
    
    hash c'est une variable spéciale, une structure de données
    semblable à un tableau
    Mais au lieu d'indexer les valeurs par nombre, on les cherche par nom
    les indices sont des chaînes uniques et on les appelle des clés
    On peut lire une valeur correspondant à une clé avec
    $h{"cle"} = "valeur"
    
    $rep c'est une variable scalaire
    qui contient le chemin vers le répertoire
    dans lequel on a les fichies log
    =cut
    my (@fichiers,%h);
    my $rep="/home/lami20j/jojo";
    
    =pod
    opendir c'est une fonction
    qui perment de lire un répertoire
    =cut
    opendir (REP,$rep)
       or die "E/S : $!\n";
    
    =pod
    open c'est une fonction
    qui permet d'ouvrie un canal
    de communication vers en fichier.
    il y a plusieurs modes d'établir 
    le canal de communication : lecture, écriture, ajout, etc.
    dans notre cas on a ouvert le mode écriture (>)
    =cut
    open F_ECRIRE,">jojo_resultat"
       or die "E/S : $!\n";
    
    =pod
    jusqu'ici on a préparé le terrain pour traitment
    tout ce que tu vois après while c'est le traitement
    de fichiers
    c'est parti...
    en premier temps je lit le répertoire
    et je stocke dans le tableau @fichiers
    le nom de fichiers auquel j'ajoute aussi le chemin
    sauf les fichiers qui commence avec . et ..
    Pourquoi . et .. ?
    .  c'est le répertoire courant
    .. c'est le répertoire parent
    =cut
    while (defined (my $fic = readdir(REP))){
      push @fichiers,"$rep/$fic" unless $fic=~/^\./;
    }
    
    =pod
    pour chaque fichier contenu dans @fichiers
    j'ouvre le fichier en lecture ou j'affiche un message 
    ensuite tant que je n'atteint pas la fin de fichier
    pour chaque couple s=Nombre (s=1,s=2,.. seront les clés de notre hash)
    je compte combien de couple j'ai
    
    Exemple:
    on a 3 s=1
    
    la clé est "s=1" et on a vu plus haut que la clé est unique
    donc au début la valeur qui correspond à la clé est indéfini(undef)
    A savoir que s'il la valeur est traité en tant que chaîne elle vaut la chaîne vide ""
    si est traité en tant que nombre elle vaut 0
    
    ${"s=1"}=${"s=1"}+1
    donc à la fin on aura
    ${"s=1"}=3
    
    donc c'est comme ça que je compte les nombre de s=1,s=2,...
    
    /(s=\d+)/ig;
    
    c'est une expression régulière (regex)
    // se sont les délimiteurs de la regex
    les paranthèses permet la capture de motif trouvé dans la variable $1
    s= c'est la chaîne littérale
    \d c'est une classe de caractère qui correspond à tout chiffre de 0 à 9
    + c'est un quantificateur qui perment de reconnaître au minimum une chiffre
    i c'est un modificateur de regex qui permet à la regex d'être insensible à la casse
      donc la regex peut reconnaître s ou S
    =cut
    foreach my $fic(@fichiers){
      open F_LIRE,"$fic"
          or warn "E/S : $!\n";
       while(<F_LIRE>){
          $h{$1}++ if /(s=\d+)/i;
       }
    }
    
    
    =pod
    j'écrit dans le fichier en utilisant le canal de communication (handle)
    qu'on a ouvert plus haut
    
    $_     represente la clé  ( s=1,...)
    $h{$_} c'est la valeur ( le nombre de chaque s=N)
    sort c'est une fonction qui va trier les s=N 
    keys %h c'est un tableau qui contient les clés de hash
    
    en bref la ligne de code on peut l'interpreté 
    
    écrit dans le fichier résultat la clé et le nombre d'occurences pour chaque clé dans le tableau de clés qui soit trié
    =cut
    print F_ECRIRE "$_ $h{$_}\n" foreach (sort keys %h);
    __END__
    
    Tout ce que tu vois entre les balises
    =pod
    
    =cut
    
    se sont de commentaires
    de même tout ce que tu vois après __END__
    n'est pas lu par l'interpreteur perl
    
    Tu vois que je n'utilise plus le même code
    que dans le 1er script, puisque le résultat que tu demandes
    et bien plus facile que je croyais
    
    0
    1. jojo
       
      salut,
      super merci
      merci d'avoir consacré du temps
      je test cette solution demain
      bonsoir
      jojo
      0
    2. jojo
       
      j'ai oublié il manque une précision
      c'est la date sous sa forme 200701
      parce que j'ai des rotate de fichier de log à 50mo et il se peut
      que le fichier log contienne des dates de 200612 et 200701
      dont si je veux extraire mes résultats et il faut que je précise la date recherchée.
      même si je dois aller dans le script pour mettre la date recherchée ça me dérange pas.
      merci
      salut
      0
  8. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    donc si je comprends bien, il faut calculer le nombre de s=1,... en fonction de la date

    en ce cas j'aimerai bien que tu me montre quelques ligne de ton log pour pouvoir faire les modifications dans le script
    0
    1. jojo
       
      bonsoir,
      oui en fonction de la date.
      si je cherche pour le mois de décembre il me faut tout 200612 et laisser 200701.
      chaque ligne commence par la date.
      merci
      salut
      0
    2. jojo
       
      bonjour,
      ça devient difficile d'échanger sur ce forum, le soir c'est quasi inaccessible.
      j'ai fait un test ça marche ! super
      j'ai juste déclaré la variable $fic au début parce que le répertoire contient bien d'autres fichiers.
      my $fic="message_log*";
      j'ai modifié my $fic après defined en $fic
      while (defined ($fic = readdir(REP))){
      c'est quoi defined ?
      merci
      salut
      0
    3. jojo
       
      salut
      j'ai un problème !
      ça ne marche pas avec des valeurs décimales
      et oui je me suis aperçu qu'il y avait des 0,xx 1,xx
      que faire ?
      merci
      a+
      jojo
      0
  9. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    ça ne marche pas avec des valeurs décimales
    et oui je me suis aperçu qu'il y avait des 0,xx 1,xx
    que faire ?


    Essaie de remplacer cette ligne
    $h{$1}++ if /(s=\d+)/i;

    avec celle ci
          $h{$1}++ if /(s=\d+[,.]?\d*)\s*/i;

    ou avec celle ci (si tu as des entrées de genre .2 ou ,2)
          $h{$1}++ if /(s=(?:\d+(?:[,.]?\d*)?|\[,.]\d+))\s*/i;
    je n'est pas testé, j'ai écrit à la volée :-))
    A toi de me dire si ça marche ou pas :-)
    0
  10. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Re,

    c'est quoi defined ?
    Reagarde ce que veut dire defined
    0
    1. jojo
       
      bonsoir,
      ça marche bien avec la première solution, j'ai pas testé la deuxième.
      j'ai encore une question (voir plus haut) comment executer ce script en ayant au préalable précisé la date.
      il faut que je recherche tout ce qui est 200612
      ayant comme valeur s=
      autre question comment rechercher une chaîne avec les mots
      entrée
      sortie
      merci beaucoup
      salut
      0