salut,
je parcours un fichier, écrit de la manière suivante:
PORTE a,b,c,d,e,f,g,
h,i,j,k,
je dois afficher:
a PORTE
b PORTE
c PORTE
d PORTE
e PORTE
f PORTE
g PORTE
....
comment je vais faire?
merci
salut,
je parcours un fichier, écrit de la manière suivante:
PORTE a,b,c,d,e,f,g,
h,i,j,k,
je dois afficher:
a PORTE
b PORTE
c PORTE
d PORTE
e PORTE
f PORTE
g PORTE
....
comment je vais faire?
merci
Bonne question ! Comment vas-tu faire ?Envoyé par bezoindaidde
Tu vas lire le fichier et le parser.
Par exemple :
Ou quelque chose comme ça. (à vrai dire, s'il y a vraiment des sauts de ligne en plein dans ta liste comme dans ton exemple, ça va être un peu plus compliqué)
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 #!/usr/bin/env perl use strict; use warnings; my $filename = shift; open my($data_src), '<', $filename or die "Couldn't open $filename : $!\n"; while( <$data_src> ){ my( $nature, $list ) = m/^(\w+)\s+(.+)$/; my @list = split /,/, $list; print "$_ $nature\n" for @list; } close $data_src; __END__
--
Jedaï
veux tu bien m'expliquer le code??
g du mal à le comprendre le principe...c'est quoi shift, > ...etc?
my( $nature, $list ) = m/^(\w+)\s+(.+)$/; ????
excuse moi, c'est que du perl ??
J'utilise un certain nombre d'idiômes dans mon script, néanmoins rien d'affolant. Par exemple quand tu vois une fonction que tu ne connais pas "shift" ici, tu devrais avoir le réflexe de regarder sa documentation (en tapant "perldoc -f shift" dans une console, ou en consultant le site perldoc, ou la traduction partielle en français). Tu as alors ta réponse (ou pas, selon ton expérience de programmateur...) :
@ARGV est un nom très souvent utilisé (dans beaucoup de langages) pour le tableau des arguments de la ligne de commande. Autrement dit, mon "shift" ici récupère le premier argument de mon programme.Retourne la première valeur d'un tableau après l'avoir supprimée du tableau en rétrécissant sa taille de 1 et en déplaçant tout vers le bas. Renvoie undef si il n'y a pas d'éléments dans le tableau. Si TABLEAU est omis, shift agira soit sur le tableau @_ s'il est dans la portée lexicale d'une subroutine ou d'un format, soit sur le tableau @ARGV s'il est dans la portée lexicale d'un fichier
Quant à tes autres questions, malheureusement "..." n'est pas suffisamment expressif pour que je comprenne ce qu'elles sont...
Et bien dire qu'il ne s'agit que de Perl serait légèrement polémique : en effet la partie m/.../ est écrite dans le langage des regex (expressions régulières), qui permet de parser (c'est à dire décomposer en éléments lexicaux) facilement des expressions simples sous formes de chaînes de caractères. Les regex sont très utilisées en Perl car elles y sont très faciles d'emploi (bien plus que dans la plupart des langages qui permettent leur utilisation).Envoyé par bezoindaidde
Une version légèrement retouchée de mon script, avec commentaires à la clé :
Ca va mieux comme ça ? Néanmoins dis-toi bien qu'on ne prendra pas toujours le temps de te faire un joli code commenté de bout en bout comme celui-ci, il va falloir apprendre un peu les bases de la programmation en Perl pour pouvoir lire un code basique comme une ouverture de fichier suivi d'une lecture et décomposition avec regex, c'est le schéma de base de beaucoup de programmes après tout (Perl est très utilisé pour faire du traitement ou du filtrage de données, texte ou binaires).
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 #!/usr/bin/env perl use strict; use warnings; # récupérer le premier argument du script # on suppose qu'il s'agit du nom du fichier à traiter my $filename = $ARGV[0]; # on ouvre le fichier en lecture ('<'), le handle de fichier est $data_src open my($data_src), '<', $filename or die "Couldn't open $filename : $!\n"; # boucle de lecture, on lit ligne par ligne dans $line while( my $line = <$data_src> ){ # on extrait "PORTE" dans $nature et la liste dans $list_string my( $nature, $list_string ) = ($line =~ m/^(\w+)\s+(.+)$/); # on découpe notre liste selon les virgules et on place ses éléments # dans le tableau @list my @list = split /,/, $list_string; # on itère sur les éléments de @list en les plaçant tour à tour dans $object for my $object ( @list ){ # on fait l'affichage tel que tu l'as indiqué print "$object $nature\n"; } } # on referme le fichier close $data_src; __END__
--
Jedaï
merci pr l'effort !
g compris le code, ça marche bien mais que pour une ligne, il m'affiche pas le reste:
par exple:
PORTE a,b,c,d,e,f,g,
h,i,j,k,
il affiche:
a PORTE
b PORTE
c PORTE
d PORTE
e PORTE
f PORTE
g PORTE
mais ne m'affiche pas:
h PORTE
i PORTE
j PORTE
k PORTE
est ce que vous avez une idée??
(j'ai pensé à raisonner par rapport à la virgule, mais il se peut que dans ma ligne j'ai des données qui ne correspondent pas à PORTE, néanmoins la ligne contient des virgules..)
Alors on complique un peu la boucle de lecture :
--
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 #!/usr/bin/env perl use strict; use warnings; my $filename = shift; open my ($data_src), '<', $filename or die "Couldn't open $filename : $!\n"; my($nature, $list); while (<$data_src>) { chomp; if ( m/^(\w+)\s+([^\s]+)$/ ) { ( $nature, $list ) = ( $1, $2 ); my @list = split /,/, $list; print "$_ $nature\n" for @list; } else { my @list = split /,/; print "$_ $nature\n" for @list; } } close $data_src; __END__
Jedaï
bon j'essaie de comprendre ton programme, aprés de petites modifs pr l'adapter à mon texte, je le compile et ça marche.
seulement kan je fais:
@array = <$data_src>;
et j'initialise un compteur : $cpt =0;
en faisant:
while ($array[$cpt])
if ($array[$cpt]=~ m/^(\w+)\s+([^\s]+)$/ ) (pour raisonner par rapport à chaque ligne de mon fichier, car j'en ai plusieurs)
dans ce cas là, je comprends pas, je retrouve le même prob qu'avant, il prend en compte que la ligne elle même : (PORTE a,b,c,d,)
pour l'autre cas (else) ca ne marche pas.
est ce que c différent de ce que lorsqu'on met:
while (<$data_src>) ????
parce que finalement je dois traiter mon fichier ligne par ligne en ayant comme mot clé ORTE.
car je dois traiter le cas de PORTE, PORTE 1, PORTE 2.... ça dépend des cas.
j'espère que je me suis faite comprise.
j'atten ton feed back.
merci
Non, tu ne t'es pas vraiment faite comprendre, désolé mais il va me falloir un échantillon plus vaste des données en entrée pour pouvoir donner une réponse plus précise. De ce que j'en avais compris, mon script fonctionnait parfaitement mais bien sûr ton exemple était extrèmement sommaire...Envoyé par bezoindaidde
??
Code : Sélectionner tout - Visualiser dans une fenêtre à part while ($array[$cpt])
C'est quoi ça ? Pourquoi tu préfères lire l'intégralité du fichier puis le traiter ligne par ligne au lieu de simplement lire ligne par ligne ? Par ailleurs pour parcourir un tableau en Perl, on utilise pas vraiment un compteur avec une boucle while (mais sur quoi porte donc ton test s'il ne porte pas sur le compteur ??), mais plutôt la boucle for (parfois écrite foreach, mais les deux appellations sont synonymes).
--
Jedaï
d'accord, je vais essayer de te donner un exemple encore plus concret:
dans mon fichier qui est énorme: (il y a énormèment de modules)
voici le bloc qui m'intéresse:
module portes (a,b,c,d,e,f,g,h,i,
j,k,l,m,n,o,p,q,u,r,s);
PORTE a;
PORTE1 b,c,d,e,f;
PORTE2 g;
test [0:1]
PORTE1 i,j,k,l,
p,d,a,u,r,s;
.
.
.
endmodule
l'objectif est de parcourir mon fichier ligne par ligne, une fois je retrouve la ligne : module portes, je vois ce qui est aprés, à chaque fois que j'ai PORTE, ou PORTE1, ou PORTE2, je dois afficher les données comme je l'ai expliqué avant.
notamment pour cet exemple, je dois afficher:
a PORTE
b PORTE1
c PORTE1
d PORTE1
e PORTE1
f PORTE1
g PORTE2
i PORTE1
j PORTE1
l PORTE1
p PORTE1
d PORTE1
a PORTE1
u PORTE1
r PORTE1
s PORTE1
voilà donc pourquoi à l'intérieur du if, que t'as déja écrit dans ton script, je suppose qu'il faudra que je mette aussi une condition genre:
if ($array[$cpt]= ~/PORTE1/) par exple qd il s'agit de PORTE1.
Pourquoi voudrait-on individualiser le cas de PORTE1 ou de PORTE2 plus qu'un autre ? Non, ces cas là sont déjà traités correctement, les seuls problèmes que peuvent poser ton fichier ce sont les types de lignes que tu n'avais pas mis dans ton exemple (module, endmodule et test) et le fait que les lignes se finissent par des point-virgules ce que tu avais également oublié... "Garbage in, garbage out" disent les anglais : si tu ne nous donnes pas les données correctes, nous ne risquons pas de te donner des réponses correctes.Envoyé par bezoindaidde
Essayons encore, néanmoins je doute que ton nouvel exemple soit plus exhaustif que le précédent...
Je ne t'aiderais pas plus loin, essaie de comprendre ce que je fais (je mimique une petite machine à état), d'apprendre les regexs, et d'étendre le script si nécessaire. Mais sans en bouleverser la structure comme avec ton tableau, ça ne devrait pas être nécessaire (et peu recommandable si tes fichiers sont vraiment gros...).
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 #!/usr/bin/env perl use strict; use warnings; my $filename = shift; open my ($data_src), '<', $filename or die "Couldn't open $filename : $!\n"; my ( $module, $in_list_to_print, $nature, $list ); while (<$data_src>) { chomp; if (m/^module \s+ (\w+) \s* \( ([a-z,]*) (?:\);)? \s* $/x) { $module = $1; $in_list_to_print = 0; # peut-être à étendre plus tard ? } elsif (m/^endmodule \s* $/x) { undef $module; } elsif (m/^test \s+ (\[.*?\]) .* $/x) { $in_list_to_print = 0; # idem ? } elsif (m/^(\w+) \s+ ([a-z,]+) ;? \s* $/x) { ( $nature, $list ) = ( $1, $2 ); my @list = split /,/, $list; print "$_ $nature\n" for @list; $in_list_to_print = 1; } elsif ( $in_list_to_print and m/^([a-z,]+) ;? \s* $/x ) { my @list = split /,/, $1; print "$_ $nature\n" for @list; } } close $data_src; __END__
--
Jedaï
je te remercie, je lirais ton code, et j'essaierais de le comprendre.
le prob que je trouve dans ton code, c'est qu'il me prend tous les modules qui existent dans mon fichier et m'affiche le contenu, alors que ce qui m'intéresse c juste le module portes. je vois pas ou est ce que je dois lui mettre la condition, pour qu'il ne me fasse le traitement que sur le module portes.
genre
while ($ligne = ~/portes\s+/) ou un truc comme ça, surout au niveau des regex que t'as mis.
là par exple :
if ($ligne =~ /^module \s+ (\w+) \s* \( ([a-z,]*) (?:\)? \s* $/x)
je la modifie en mettant:
if ($ligne =~ /^module \s+ (\portes) \s* \( ([a-z,]*) (?:\)? \s* $/x)
ou
if ($ligne =~ /^module \s+ portes \s* \( ([a-z,]*) (?:\)? \s* $/x)
les deux ne marchent pas.
je sais que j'ai abusé, mais chui débutant en perl, encore un coup de pouce sur ce point, et je n'en ajouterais pas !
D'accord je vois, dans ce cas la modification à apporter est en fait minime, toute l'infrastructure est déjà en place, il faut juste vérifier qu'on est bien dans le module "portes" avant d'afficher :
--
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 #!/usr/bin/env perl use strict; use warnings; my $filename = shift; open my ($data_src), '<', $filename or die "Couldn't open $filename : $!\n"; my ( $module, $in_list_to_print, $nature, $list ); while (<$data_src>) { chomp; if (m/^module \s+ (\w+) \s* \( ([a-z,]*) (?:\);)? \s* $/x) { $module = $1; $in_list_to_print = 0; # peut-être à étendre plus tard ? } elsif (m/^endmodule \s* $/x) { $module = ''; $in_list_to_print = 0; } elsif (m/^test \s+ (\[.*?\]) .* $/x) { $in_list_to_print = 0; # idem ? } elsif ( $module eq 'portes' and m/^(\w+) \s+ ([a-z,]+) ;? \s* $/x ) { ( $nature, $list ) = ( $1, $2 ); my @list = split /,/, $list; print "$_ $nature\n" for @list; $in_list_to_print = 1; } elsif ( $in_list_to_print and m/^([a-z,]+) ;? \s* $/x ) { my @list = split /,/, $1; print "$_ $nature\n" for @list; } } close $data_src; __END__
Jedaï
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager