[Perl] débutant chercher conseil

Fermé
jojo - 27 janv. 2007 à 16:09
 jojo - 7 févr. 2007 à 17:30
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

9 réponses

lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
27 janv. 2007 à 16:35
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
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
bonsoir,
alors personne peut m'aider sur mon problème ?
merci
jojo
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
29 janv. 2007 à 00:14
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
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
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
29 janv. 2007 à 20:24
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
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
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
30 janv. 2007 à 19:07
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
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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
30 janv. 2007 à 21:38
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
c'est ça
merci
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567 > jojo
31 janv. 2007 à 12:45
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
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
31 janv. 2007 à 20:26
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
salut,
super merci
merci d'avoir consacré du temps
je test cette solution demain
bonsoir
jojo
0
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
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
1 févr. 2007 à 07:25
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
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
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
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
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
3 févr. 2007 à 19:14
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
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
3 févr. 2007 à 19:17
Re,

c'est quoi defined ?
Reagarde ce que veut dire defined
0
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