Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Question débutant - Expression régulière

12 réponses
Avatar
Bob
Bonjour,
Je suis débutant en Perl et je dois faire un script Perl pour demain :-(
Le principe est assez simple : je lis un fichier, j'en extrais des lignes
suivant un critère.

Le fichier est composée d'enregistrement et chaque enregistrement de 3
valeurs séparées par le caractère ";"
Exemple :

Enregistrement 1 Valeur 1;Enregistrement 1 Valeur 2;Enregistrement 1 Valeur
3;
Enregistrement 2 Valeur 1;Enregistrement 2 Valeur 2;Enregistrement 2 Valeur
3;
Enregistrement 3 Valeur 1;Enregistrement 3 Valeur 2;Enregistrement 3 Valeur
3;
Enregistrement 4 Valeur 1;Enregistrement 4 Valeur 2;Enregistrement 4 Valeur
3;


J'ai la lecture du fichier qui fonctionne mais je n'arrive pas à composer
l'expression régulière d'extraction des valeurs.

open(MONFICHIER, $sourceFic);

while(<MONFICHIER>) {
chomp;
$_ =~/^(\w*);(\w*);(\w*).*/;
print $1,"\n";
print $2,"\n";
print $3,"\n";
}

close MONFICHIER;

10 réponses

1 2
Avatar
kurtz le pirate
In article , "Bob"
wrote:

::Bonjour,
::Je suis débutant en Perl et je dois faire un script Perl pour demain :-(
::Le principe est assez simple : je lis un fichier, j'en extrais des lignes
::suivant un critère.
::
::Le fichier est composée d'enregistrement et chaque enregistrement de 3
::valeurs séparées par le caractère ";"
::Exemple :
::
::Enregistrement 1 Valeur 1;Enregistrement 1 Valeur 2;Enregistrement 1 Valeur
::3;
::Enregistrement 2 Valeur 1;Enregistrement 2 Valeur 2;Enregistrement 2 Valeur
::3;
::Enregistrement 3 Valeur 1;Enregistrement 3 Valeur 2;Enregistrement 3 Valeur
::3;
::Enregistrement 4 Valeur 1;Enregistrement 4 Valeur 2;Enregistrement 4 Valeur
::3;
::
::
::J'ai la lecture du fichier qui fonctionne mais je n'arrive pas à composer
::l'expression régulière d'extraction des valeurs.

c'est à dire ?
tu veux : "Enregistrement 1 Valeur 1"
ou "Valeur 1" ??


::open(MONFICHIER, $sourceFic);
::
::while(<MONFICHIER>) {
:: chomp;
:: $_ =~/^(w*);(w*);(w*).*/;
:: print $1,"n";
:: print $2,"n";
:: print $3,"n";
::}
::
::close MONFICHIER;

peut être avec :
($a, $b, $c) = split /;/


klp
Avatar
J.Pierre Pourrez
Le Sun, 04 Sep 2005 10:11:23 +0200, Bob a écrit :

Bonjour,
Je suis débutant en Perl et je dois faire un script Perl pour demain :-(
Le principe est assez simple : je lis un fichier, j'en extrais des lignes
suivant un critère.

Le fichier est composée d'enregistrement et chaque enregistrement de 3
valeurs séparées par le caractère ";" Exemple :

Enregistrement 1 Valeur 1;Enregistrement 1 Valeur 2;Enregistrement 1
Valeur 3;
Enregistrement 2 Valeur 1;Enregistrement 2 Valeur 2;Enregistrement 2
Valeur 3;
Enregistrement 3 Valeur 1;Enregistrement 3 Valeur 2;Enregistrement 3
Valeur 3;
Enregistrement 4 Valeur 1;Enregistrement 4 Valeur 2;Enregistrement 4
Valeur 3;


J'ai la lecture du fichier qui fonctionne mais je n'arrive pas à composer
l'expression régulière d'extraction des valeurs.

open(MONFICHIER, $sourceFic);

while(<MONFICHIER>) {
chomp;
$_ =~/^(w*);(w*);(w*).*/;
print $1,"n";
print $2,"n";
print $3,"n";
}
}
close MONFICHIER;


La fonction split serait plus approprié:

perldoc -f split

------8<-------8<------8<------8<------8<------8<------8<------8<------
#!/usr/bin/perl -w

my @liste=('Ceci est beau;que faire;cette étagère',
'Dimanche;Robinson;Ca alors');

foreach $ligne (@liste) {
chomp $ligne;
my @champs = split /;/, $ligne;
print join "n", @champs;
print "nn";
}
------8<-------8<------8<------8<------8<------8<------8<------8<---

N.B.: ";" est un séparateur d'instruction. Donc, mieux vaut l'échapper
pour éviter qu'il soit interpréter.

Cordialement
Jean-Pierre

Avatar
Patrick Texier
Le Sun, 4 Sep 2005 10:11:23 +0200, "Bob" a écrit :

J'ai la lecture du fichier qui fonctionne mais je n'arrive pas à composer
l'expression régulière d'extraction des valeurs.


Il ne faut une expression rationnelle mais un split tout bête. Voir la
doc des fonctions Perl (la fonction inverse est join).

open(MONFICHIER, $sourceFic);

while(<MONFICHIER>) {
chomp;
$_ =~/^(w*);(w*);(w*).*/;


my @tableau = split /;/;
--
Patrick Texier

Tous les résultats de GP F1 librement téléchargeables
http://www.genindre.org/perso/f1.htm

Avatar
Benoit Izac
Bonjour,

le 04/09/2005 à 10:11, "Bob" a écrit
dans le message :

Le fichier est composée d'enregistrement et chaque enregistrement de 3
valeurs séparées par le caractère ";"
Exemple :

Enregistrement 1 Valeur 1;Enregistrement 1 Valeur 2;Enregistrement 1
Valeur 3;

J'ai la lecture du fichier qui fonctionne mais je n'arrive pas à
composer l'expression régulière d'extraction des valeurs.

open(MONFICHIER, $sourceFic);


Toujours vérifier que open à bien fonctionné :
open(MONFICHIER, '<', $sourceFic)
or die "je ne peux pas ouvrir $sourceFic : $!";

while(<MONFICHIER>) {
chomp;
$_ =~/^(w*);(w*);(w*).*/;


Ici tu n'est pas sûr d'avoir une correspondance ce qui fait que $1, $2
et $3 peuvent être vide :
if (/REGEXP/) {
# code sur $1, $2, $3
}

Pour la regexp, ici tu cherches une chaîne commençant par zéro ou
plusieurs caractères (alphanumérique ou « _ ») suivi d'un « ; », etc.
Ça ne peut pas fonctionner pour l'exemple que tu a présenté ci-dessus.
avec /^([^;]*);([^;]*);([^;]*);$/, tu as les valeurs 1, 2 et 3
respectivement dans $1, $2 et $3 ; si tu veux savoir à quel
enregistrement elles correspondent il te faut en plus une variable que tu
incrémentes à chaque while.

Moi, je ferais ça :

#!/usr/bin/perl
use warnings;
use strict;

my $file = 'input_file';

open(my $fh, '<', $file) or die "can't open $file: $!";

my $n = 0;
while (<$fh>) {
++$n;
chomp;

if (/^([^;]*);([^;]*);([^;]*);$/) {
print "record $n, value 1 = ``$1''n";
print "record $n, value 2 = ``$2''n";
print "record $n, value 3 = ``$3''n";
} else {
print STDERR "record $n is not validn";
}
}

close($fh);
__END__


Si c'est pour un devoir, n'oublie pas de me donner ma note ;-)
--
Benoit Izac

Avatar
Bob
Merci pour les premières réponses.
Ce que je souhaite récupérer c'est tout les caractères compris entre les ";"
Pour ce qui est de l'utilisation du "split" je pensais qu'une expression
régulière serait plus performante.
Je dois filtrer les lignes en fonction de la valeur d'un champ sur un
fichier texte de plus de 2 Go.
Le simple "balayage" du fichier s'effectue pour l'instant en 7 minutes.
Merci encore pour votre aide.
Bob


"Bob" a écrit dans le message de news:

Bonjour,
Je suis débutant en Perl et je dois faire un script Perl pour demain :-(
Le principe est assez simple : je lis un fichier, j'en extrais des lignes
suivant un critère.

Le fichier est composée d'enregistrement et chaque enregistrement de 3
valeurs séparées par le caractère ";"
Exemple :

Enregistrement 1 Valeur 1;Enregistrement 1 Valeur 2;Enregistrement 1
Valeur 3;
Enregistrement 2 Valeur 1;Enregistrement 2 Valeur 2;Enregistrement 2
Valeur 3;
Enregistrement 3 Valeur 1;Enregistrement 3 Valeur 2;Enregistrement 3
Valeur 3;
Enregistrement 4 Valeur 1;Enregistrement 4 Valeur 2;Enregistrement 4
Valeur 3;


J'ai la lecture du fichier qui fonctionne mais je n'arrive pas à composer
l'expression régulière d'extraction des valeurs.

open(MONFICHIER, $sourceFic);

while(<MONFICHIER>) {
chomp;
$_ =~/^(w*);(w*);(w*).*/;
print $1,"n";
print $2,"n";
print $3,"n";
}

close MONFICHIER;





Avatar
Laurent Wacrenier
J.Pierre Pourrez écrit:
N.B.: ";" est un séparateur d'instruction. Donc, mieux vaut l'échapper
pour éviter qu'il soit interpréter.


Pas dans une expression rationnelle.

Avatar
Bob
Merci Benoit,
Je te rassure ce n'est pas pour l'école, j'ai passé l'age (41)
malheureusement :-(
Par contre à partir de ce que tu m'as donné j'ai réussi à me débrouiller.
En mettant cela
$_ =~/([^;]*);([^;]*);([^;]*);.*/;
ça marche parfaitement.
Le dernier point qu'il me reste à traiter c'est le tri des lignes filtrées.
Je dois trier sur l'une ou plusieurs des 3 colonnes et comme mon fichier
fait entre 12 et 15 millions de lignes je me demande si ce n'est pas
utopique de penser pouvoir le faire avec PERL.
Si tu as un avis.
Bob


"Benoit Izac" a écrit dans le message de
news:
Bonjour,

le 04/09/2005 à 10:11, "Bob" a écrit
dans le message :

Le fichier est composée d'enregistrement et chaque enregistrement de 3
valeurs séparées par le caractère ";"
Exemple :

Enregistrement 1 Valeur 1;Enregistrement 1 Valeur 2;Enregistrement 1
Valeur 3;

J'ai la lecture du fichier qui fonctionne mais je n'arrive pas à
composer l'expression régulière d'extraction des valeurs.

open(MONFICHIER, $sourceFic);


Toujours vérifier que open à bien fonctionné :
open(MONFICHIER, '<', $sourceFic)
or die "je ne peux pas ouvrir $sourceFic : $!";

while(<MONFICHIER>) {
chomp;
$_ =~/^(w*);(w*);(w*).*/;


Ici tu n'est pas sûr d'avoir une correspondance ce qui fait que $1, $2
et $3 peuvent être vide :
if (/REGEXP/) {
# code sur $1, $2, $3
}

Pour la regexp, ici tu cherches une chaîne commençant par zéro ou
plusieurs caractères (alphanumérique ou « _ ») suivi d'un « ; », etc.
Ça ne peut pas fonctionner pour l'exemple que tu a présenté ci-dessus.
avec /^([^;]*);([^;]*);([^;]*);$/, tu as les valeurs 1, 2 et 3
respectivement dans $1, $2 et $3 ; si tu veux savoir à quel
enregistrement elles correspondent il te faut en plus une variable que tu
incrémentes à chaque while.

Moi, je ferais ça :

#!/usr/bin/perl
use warnings;
use strict;

my $file = 'input_file';

open(my $fh, '<', $file) or die "can't open $file: $!";

my $n = 0;
while (<$fh>) {
++$n;
chomp;

if (/^([^;]*);([^;]*);([^;]*);$/) {
print "record $n, value 1 = ``$1''n";
print "record $n, value 2 = ``$2''n";
print "record $n, value 3 = ``$3''n";
} else {
print STDERR "record $n is not validn";
}
}

close($fh);
__END__


Si c'est pour un devoir, n'oublie pas de me donner ma note ;-)
--
Benoit Izac



Avatar
Benoit Izac
Bonjour,

le 04/09/2005 à 18:47, "Bob" a écrit
dans le message :

Le dernier point qu'il me reste à traiter c'est le tri des lignes
filtrées. Je dois trier sur l'une ou plusieurs des 3 colonnes et
comme mon fichier fait entre 12 et 15 millions de lignes je me demande
si ce n'est pas utopique de penser pouvoir le faire avec PERL.


soit ton fichier :
champ_1.1;champ_1.2;champ_1.3;
champ_2.1;champ_2.2;champ_2.3;
champ_3.1;champ_3.2;champ_3.3;
...
champ_n.1;champ_n.2;champ_n.3;

Tu veux trier selon quelle colonne ?
Dans quel ordre (alphabétique, numérique) ?

Pour un fichier de cette taille, si tu es sur un système Posix, la
commande sort(1) me parait effectivement mieux adapté. Tu peux faire un
trie selon plusieurs champs (regarde les options -t et -k).

Sinon, il y a toujours moyen de le faire en Perl mais ça te coûtera plus
cher en :
- temps d'écriture du programme
- temps d'execution
- mémoire vive ou espace disque

--
Benoit Izac

Avatar
Benoit Izac
Dans le message ,

Pour un fichier de cette taille, si tu es sur un système Posix, la
commande sort(1) me parait effectivement mieux adapté. Tu peux faire
un trie selon plusieurs champs (regarde les options -t et -k).

Sinon, il y a toujours moyen de le faire en Perl mais ça te coûtera
plus cher en :
- temps d'écriture du programme
- temps d'execution
- mémoire vive ou espace disque


D'ailleurs, il serait intéressant d'essayer File::Sort
<http://search.cpan.org/~cnandor/File-Sort/Sort.pm> sur un fichier de
cette taille.

--
Benoit Izac

Avatar
Bob
Re,
Malheureusement je suis sous Windows.
Je vais regarder avec attention l'url que vous m'avez passé.
Merci encore pour votre temps.
Bob

"Benoit Izac" a écrit dans le message de
news:
Dans le message ,

Pour un fichier de cette taille, si tu es sur un système Posix, la
commande sort(1) me parait effectivement mieux adapté. Tu peux faire
un trie selon plusieurs champs (regarde les options -t et -k).

Sinon, il y a toujours moyen de le faire en Perl mais ça te coûtera
plus cher en :
- temps d'écriture du programme
- temps d'execution
- mémoire vive ou espace disque


D'ailleurs, il serait intéressant d'essayer File::Sort
<http://search.cpan.org/~cnandor/File-Sort/Sort.pm> sur un fichier de
cette taille.

--
Benoit Izac



1 2