Chaine de caractère

flongo Messages postés 61 Statut Membre -  
flongo Messages postés 61 Statut Membre -
Bonjour,

Je travaille sous PERL.

J'ai différentes lignes d'informations.
La 1ere ligne commence par l'expression "INFO : Close File".
Ma deuxieme ligne commence par diférents mots: soit type,soit reception.
Ma derniere ligne commence tjrs par "FIN IMPORT".

Exemple de fichiers :
INFO : Close File........................
Reception................
.....
FIN IMPORT...................

OU/ET

INFO : Close File........................
Type................
.....
FIN IMPORT...................

Je veux créer un txt pour les lignes d'infos dont la 2eme ligne commence par "type" et un autre txt dont la 2eme ligne commence par "reception".
Voila ce que j'ai fait mais le hic c'est qu'en faisant ca, je perd la 1ere ligne:

while (<FICHIER>) {
print WRITER if /Reception/ .. /FIN IMPORT/;
\n;

}

Je veux garder la 1ere ligne automatiquement.
Merci pour votre aide.
A voir également:

10 réponses

flongo Messages postés 61 Statut Membre
 
bonjour,

j'ai un fichier de ce type :

INFO : Close File........................
Reception................
.....
FIN IMPORT...................

INFO : Close File........................
Type................
.....
FIN IMPORT...................

Je veux créer un txt pour les lignes d'infos dont la 2eme ligne commence par "type" et un autre txt dont la 2eme ligne commence par "reception".

J'ai fait ce code mais ca marche pas comme je veux:
open FICHIER,"<P:\\Prog_perl\\Infos_pivot1.txt"
or die "Ce fichier n'existe pas!";

open WRITER, ">P:\\Prog_perl\\Tab1_type.txt"
or die "Le fichier ne peut etre édité!";

$ligne =<FICHIER> ;

foreach ($ligne) {
if (substr($ligne,48)="Reception"){
print WRITER;
}
}

__END__

Ce que je veux au final c'est avoir un txt avec des infos de ce type:

INFO : Close File........................
Type ................
.....
FIN IMPORT...................

INFO : Close File........................
Type................
.....
FIN IMPORT...................

Et je veux un autre txt de ce type :

INFO : Close File........................
Reception................
.....
FIN IMPORT...................

INFO : Close File........................
Reception................
.....
FIN IMPORT...................

Donc un fichier qui concerne les receptions et un autre, le type.

Quelqu'un peut il m'aider svp?
Merci d'avance
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
Salut.
Moi, dans mes comparaison de chaine j'utilise "eq" car le symbole égale me posait des problèmes.
if(substr($ligne,9) eq 'Reception')
Ensuite, il faut faire un tampon en algo :
TANT pas à la fin du fichier.
tampon=$ligne
$ligne=<FICHIER>
if($ligne == "recepction")
impression de tampon dans fichier1
tant que $ligne différent de FIN_IMPORT
lire une ligne et imprimer dans le fichier 1
Sinon, si $ligne == "type"
impression de tampon dans fichier2
tant que $ligne différent de FIN_IMPORT
lire une ligne et imprimer dans le fichier 2
fin tant que
0
loupius
 
C'est normal qu'avec '==' tu aies des problèmes, car Perl fait une comparaison en numérique; il va donc transtyper les 2 chaînes en numériques, si bien que: "toto" == "titi" est vrai puique tous deux égaux à zéro.
De même "toto" = 0 est vrai mais "toto" = 1 est faux.
Donc '==' pour les comparaisons numériques et 'eq' pour les comparaisons de chaînes; de même pour les autres opérateurs de comparaison (comparaison, différent, inférieur, ...), à chacun son opérateur.
0
flongo Messages postés 61 Statut Membre
 
Merci pour ta reponse.
J'ai essayé de transcrire ton algo mais il y a des petits trucs qui doivent pas aller:

open FICHIER,"<P:\\Prog_perl\\Infos_pivot1.txt"
or die "Ce fichier n'existe pas!";

open WRITER, ">P:\\Prog_perl\\Tab1_type.txt"
or die "Le fichier ne peut etre édité!";

open WRITER2, ">P:\\Prog_perl\\Tab2_type.txt"
or die "Le fichier ne peut etre édité!";

$ligne =<FICHIER> ;
while (pas la la fin du fichier) # Comment fait on pour dire kon est pas a la fin du fichier ?{
$ligne =<FICHIER> ;
tampon=$ligne;
if ($ligne=="Reception"){
print WRITER;
while ($ligne ne 'FIN IMPORT'){
print $ligne ; #Lire la ligne est ce bien cela?
print WRITER;
}
}
elsif ($ligne=="Reception"){
print WRITER2;
while ($ligne ne 'FIN IMPORT'){
print $ligne ;
print WRITER2;
}

}

}
close (FICHIER)
close (WRITER)
close (WRITER2)

_END_
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299 > flongo Messages postés 61 Statut Membre
 
une syntaxe, pour lire une ligne, c'est :
$ligne=<FICHIER>
print c'est pour écrire et il faut préciser le fichier de sortie.
Donc :
open FICHIER, WRITE1et WRITE 2
while (<FICHIER>) # Je crois qu'on peut faire comme ça
{
$ligne =<FICHIER> ;
$tampon=$ligne;
$ligne=<FICHIER>
if ($ligne eq "Reception"){
print WRITER "$tampon";
while ($ligne ne 'FIN IMPORT'){
print WRITER $ligne ;
$ligne=<FICHIER>
}
}
elsif ($ligne eq "Type"){
...#la même chose qu'au dessus mais avec WRITE2
}

}

}
etc.

À Fiddy : je sais que tu as donné la réponse, mais je pense que ça peut lui être utile pour la suite qu'on lui corrige son programme. (Enfin, vu mon niveau en perl, il doit rester de belles boulette). Ton programme est bien compact, mais il pique les yeux d'un débutant comme moi ;)
0
flongo Messages postés 61 Statut Membre > Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention  
 
Désolé, ca ne marche pas.
0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847
 
Salut,
Voici un programme fait à la va-vite (donc sûrement optimisable) :
#!/usr/bin/perl 
use strict;use warnings;

open(LIRE, "nomFichier") || die("erreur ouverture");
open(WRITE1, ">reception") || die("erreur écriture");
open(WRITE2, ">type") || die("erreur écriture");

my @buf=();
my $type;
while(<LIRE>){
    @buf=() if /INFO/;
    if(@buf==1){
        /(\S*)/;
        $type=$1;
    }
    push(@buf,$_) if /INFO/ .. /FIN IMPORT/;

    if(/FIN IMPORT/){
        print WRITE1 @buf if $type eq 'Reception';
        print WRITE2 @buf if $type eq 'Type';
    }
}

close(LIRE);
close(WRITE1);
close(WRITE2);

Cdlt
0
flongo Messages postés 61 Statut Membre
 
Je te remercie.

J'ai pas tres bien compri ton code, ce qui fait que j'ai du mal a trouver ce qui ne vas pas.
Quand je le lance, j'ai le message d'erreur suivant :
erreur ouverture at P:\Prog_perl\Fiddy.pl line 6.
Je me suis dit qu'il y a avait un souci sur les ouvertures de fichier mais c pas ca!

Ca peut etre koi?
0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847
 
Remplace nomFichier par le nom de ton fichier ^^.
open(LIRE, "nomFichier") || die("erreur ouverture");
0
flongo Messages postés 61 Statut Membre
 
Salut Fiddy,

Je te remercie de m'avoir donné un coup de main. Ca marche! Merci bcp.
Si possible, pourrais tu m'expliquer ce petit programme stp? Si tu as le temps!
cordialement
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
Remplace nomFichier par le nom de ton fichier
Ha ! oui, tout de même !
Petit rappel : il n'est pas interdit d'utiliser son cerveau avant de recopier quelque chose.
0
flongo Messages postés 61 Statut Membre > Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention  
 
Je sais que je suis novice dans ce langage mais je ne suis pas bete au point de ne pas remplacer nomFichier par le nom de mon fichier !

Comment on fait pour dire qu'il y a un espace en début de chaine?
0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847 > flongo Messages postés 61 Statut Membre
 
Voici le programme commenté :
#!/usr/bin/perl 
use strict;use warnings;

open(LIRE, "nomFichier") || die("erreur ouverture");
open(WRITE1, ">reception") || die("erreur écriture");
open(WRITE2, ">type") || die("erreur écriture");

my @buf=(); #déclaration et initialisation de @buf
my $type; #déclaration de $type
while(<LIRE>){ #tant qu'il y a des lignes à lire
    @buf=() if /INFO/; #si la ligne contient INFO, alors @buf=(), début d'un nouveau cycle
    if(@buf==1){ #si @buf ne contient qu'un seul élément, donc à la deuxième ligne
        /(\S*)/; #on sauvegarde le premier mot dans $1
        $type=$1; #on sauvegarde dans $type
    }
    push(@buf,$_) if /INFO/ .. /FIN IMPORT/; #on empile s'il s'agit du bon paragraphe

    if(/FIN IMPORT/){ #s'il s'agit de la ligne FIN IMPORT
        print WRITE1 @buf if $type eq 'Reception'; #on copie dans WRITE1 si $type vaut Reception
        print WRITE2 @buf if $type eq 'Type'; #on copie dans WRITE2 si $type vaut Type
    }
}

close(LIRE);
close(WRITE1);
close(WRITE2);

0

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

Posez votre question
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
Dit plutôt ce que tu ne comprends pas.
les '/' correspondent à des testes sur les chaîne de caractère en écriture raccourci.
0
flongo Messages postés 61 Statut Membre
 
Dans le prog, c koi le tampon? A quoi il sert reelement?

On peut pas mettre $tampon=<FICHIER>, au lieu de:
$ligne =<FICHIER> ;
$tampon=$ligne;
$ligne =<FICHIER>;

??????????????


Je t'ai remi le prog:

open FICHIER,"<P:\\Prog_perl\\Infos_pivot1.txt"
or die "Ce fichier n'existe pas!";

open WRITER, ">P:\\Prog_perl\\Tab1_type.txt"
or die "Le fichier ne peut etre édité!";

open WRITER2, ">P:\\Prog_perl\\Tab2_type.txt"
or die "Le fichier ne peut etre édité!";


while (<FICHIER>){
$ligne =<FICHIER> ;
$tampon=$ligne;
$ligne =<FICHIER>;
if ($ligne eq 'Reception'){
print WRITER "$tampon";
while ($ligne ne 'FIN IMPORT'){
print WRITER $ligne;
$ligne =<FICHIER>;
}
}
elsif ($ligne eq 'Type'){
print WRITER2 "$tampon";
while ($ligne ne 'FIN IMPORT'){
print WRITER2 $ligne;
$ligne =<FICHIER>;
}

}



}
close (FICHIER);
close (WRITER);
close (WRITER2);




En ce qui concerne l'espace en debut de caractère, j'ai trouvé ca:
if $type eq /\sERROR/ (ca fonctionne). Est vraiment ca ou on pouvait faire autrement?

Merci pour ton aide!
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
Ha ! c'est mon programme que tu ne comprends pas ?
en effet, il n'y a pas besoin de faire $ligne=<FICHIER> puis $tampon=$ligne, tu peux faire directement $tampon=<FICHIER>
Le tampon sert car tu lis un fichier un fichier ligne par ligne et que l'information sur où écrire est stocké à la deuxième ligne. Il faut donc sauvegarder la première ligne quelque part en attendant de savoir où la mettre.
Il y a deux approche : la mienne qui utilise ce tampon et écris ensuite ligne par ligne dans le fichier.
Et la solution de fiddy qui utilise un tampon plus gros (buf) où il stocke le bloc entier (de INFO à FIN IMPORT) avant de l'écrire dans le bon fichier suivant le type de la deuxième ligne lue.
D'autre question ?
0
flongo Messages postés 61 Statut Membre
 
En faite, ca marche tjrs pas! Je cherche la ou ca va pas!

Pourquoi, ne vaudrait il pas mieux attribuer $tampon=<FICHIER> des le début et non dans la boucle?

Voila ce ke j'ai modifié:

open FICHIER,"<P:\\Prog_perl\\Infos_pivot1.txt"
or die "Ce fichier n'existe pas!";

open WRITER, ">P:\\Prog_perl\\Tab1_type.txt"
or die "Le fichier ne peut etre édité!";

open WRITER2, ">P:\\Prog_perl\\Tab2_type.txt"
or die "Le fichier ne peut etre édité!";

$tampon=<FICHIER>;
while (<FICHIER>){
if ($tampon eq 'Reception'){
print WRITER $tampon;
while ($tampon ne 'FIN IMPORT'){
print WRITER $tampon;
#$tampon =<FICHIER>;
}
}
elsif ($tampon eq 'Type'){
print WRITER2 $tampon;
while ($tampon ne 'FIN IMPORT'){
print WRITER2 $tampon;
#$tampon=<FICHIER>;
}

}



}
close (FICHIER);
close (WRITER);
close (WRITER2);


Merci
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
ba non, il ne faut pas affecté tampon avant la boucle, sinon il ne sert que pour le premier bloc.
Une chose est sur, tu n'as rien compris à ce que je t'ai expliqué. Que ça soit mon programme ou celui de fiddy, il faut utiliser 2 variables car l'information est à la deuxième ligne.
Par contre, je pense que je fait une grosse erreur avec while(<FICHIER>) car d'après ce qu'à écris fiddy, c'est la même chose que while($_=<FICHIER>), tu lit donc une ligne du fichier.
open FICHIER, WRITE1et WRITE 2
while (<FICHIER>)
{
  $tampon=$_;
  $ligne=<FICHIER>
  if ($ligne eq "Reception"){
    print (WRITER, "$tampon");
    print (WRITER ,$ligne) ;
    while ($ligne ne 'FIN IMPORT'){
      $ligne=<FICHIER>
      print (WRITER ,$ligne) ;
    }
  }
  elsif ($ligne eq "Type"){
...#la même chose qu'au dessus mais avec WRITE2
   }

  }

} 
0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847
 
if ($ligne eq "Reception"){
Ca ne marchera pas, il n'y a pas comparaison stricte (des informations après Reception, et un \n en fin de ligne)

Voici une version correcte (j'ai essayé de garder la même structure) :
my $tampon;
my $ligne;

open(FICHIER, "nomFichier") || die("erreur ouverture");
open(WRITER1, ">reception") || die("erreur écriture");
open(WRITER2, ">type") || die("erreur écriture");

while ($tampon=<FICHIER>) # Je crois qu'on peut faire comme ça
{
    while($tampon eq "\n"){ #au cas où il y a des lignes vierges entre les paragraphes
        $tampon=<FICHIER>;
    }
    $ligne=<FICHIER>;
    if ($ligne =~ /Reception/ ){
        print WRITER1 "$tampon";
        print WRITER1 $ligne;
        while ($ligne !~ /FIN IMPORT/){
            $ligne=<FICHIER>;
            print WRITER1 $ligne;
        }   
    }   
    elsif ($ligne =~ /Type/){
        print WRITER2 "$tampon";
        print WRITER2 $ligne;
        while ($ligne !~ /FIN IMPORT/){
            $ligne=<FICHIER>;
            print WRITER2 $ligne;
        }
    }
}   

close(FICHIER);
close(WRITER1);
close(WRITER2);



Cdlt
0
lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570 > fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention  
 
Salut,

while ($tampon=<FICHIER>) # Je crois qu'on peut faire comme ça
{
while($tampon eq "\n"){ #au cas où il y a des lignes vierges entre les paragraphes
$tampon=<FICHIER>;
}
$ligne=<FICHIER>;


pour verifier les lignes vides il suffit d'utiliser la regex ^$
next if /^$/; # je ne traite pas les lignes vides

Utiliser l'opérateur <> deux fois dans la boucle je n'ai jamais vu

Quand tu fais
while($tampon=<FICHIER>){
ici $tampon contiendra une par une les lignes de fichiers
donc $ligne recevra plutôt le contenu de $tampon;
}

D'ailleurs plutôt logique pour le nom des variables sera
while($ligne=<FICHIER>){
   $tampon=$ligne;
}


Si le mode slurp n'est pas activé
$var=<FICHIER> contient la 1ère ligne de fichier
0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847 > lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention  
 
Je sais bien, mais j'ai essayé d'adapter sa version de programme en restant le plus simple possible. Ma version (sûrement contestable ^^) a été donné en #5.
0
lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570 > fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention  
 
Re,

Je n'ai pas des moyens pour tester.
Veux-tu tester le code de message 21?
Merci.
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299 > lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention  
 
Salut.
pour $tampon, c'est ce que j'avais proposer au début, mais c'est vrai que ça ne change rien, ça fait économisé une ligne.
éclaire nous sur le comportement de $var=<FICHIER>. D'après le message que tu mets, si je comprends bien, soit cette commande met une ligne dans la variable et passe à la ligne suivante lors du prochain appel, soit elle met la première ligne du fichier dans la variable à chaque appel (mais alors comment lire les autres lignes ?), ceci selon slurp est activé ou non. C'est ça ?
Sinon, qu'est-ce qui te choque d'utiliser deux fois l'opérateur <> dans une boucle ?
(Il est vrai que j'écris en perl comme j'écrirais en C, et que certaines subtilités m'échappent)
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
Bien vu fiddy ! j'y avait pensé au premier message, puis oublié après.
0
lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
Salut,

Pourquoi pas (je n'ai pas testé ;-) un truc de genre
#!/usr/bin/perl 
use strict; use warnings;

open FICHIER,  "nomFichier"      or die "E/S $!\n";
open RECEPTION,">>reception.txt" or die "E/S : $!\n";
open TYPE,     ">>type.txt"      or die "E/S : $!\n";

while (<FICHIER>) { 
  my $info=$_ if /^INFO/;
  print RECEPTION "$info $_" if /Reception/ .. /FIN IMPORT/; 
  print TYPE      "$info $_" if /Type/      .. /FIN IMPORT/;
}
__END__


0
fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention   1 847
 
Ton programme donne des warnings :
Use of uninitialized value $info in concatenation (.) or string at ./lami.pl line 10, <FICHIER> line 2.
...
Use of uninitialized value $info in concatenation (.) or string at ./lami.pl line 11, <FICHIER> line 24.

Sinon pour le résultat, il n'affiche pas la ligne INFO.
0
lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570 > fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention  
 
Re,

Merci ;-)
Je vais voir à la maison ce soir.
Mais il sera intéressant d'avoir le fichier ou au moins une partie de fichier pour tester.
0
flongo Messages postés 61 Statut Membre > fiddy Messages postés 11653 Date d'inscription   Statut Contributeur Dernière intervention  
 
Merci, ca fonctionne!

Ou je pourrai trouver le module drivers DBD::mysql. J'en ai besoin car je dois faire une base de données en mysql.
0
lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570 > flongo Messages postés 61 Statut Membre
 
Salut,

Tu diras peut être quel code fonctionne ;-))
Ensuite pour les modules il faut voir sur cpan.org
0
flongo Messages postés 61 Statut Membre > lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention  
 
Merci!

Les deux fonctionnent!
0
lami20j Messages postés 21644 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
Re,

Si tu as installer activeperl tu peux ouvrir dos et taper ppm pour installer des modules depuis cpan
0