Enlever certaines lignes d'un fichier

Résolu/Fermé
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 - 16 mai 2019 à 16:37
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 - 23 mai 2019 à 17:03
Bonjour,

Je veux extraire, d'une liste de mots présents dans un fichier (entree.txt), ceux qui se terminent par une certaine chaîne de caractères que j'aurai choisie préalablement. Le programme va enlever les mots du fichier initial entree.txt qui remplissent le critère et les insérer dans un autre fichier (sortie.txt).

Par exemple, si j'ai le fichier entree.txt suivant :

automne
bateau
brise
chameau
cheval
gâteau


et que ma chaîne est "eau" et que j'exécute mon programme, mon fichier sortie.txt doit contenir les mots suivants :

bateau
chameau
gâteau


et mon fichier initial entree.txt devient :

automne
brise
cheval


Le programme suivant :

#!/usr/bin/perl

open(INFILE, "entree.txt") or die "Le fichier ne s'ouvre pas: $!";
open(OUTFILE, ">sortie.txt") or die "Le fichier ne s'ouvre pas: $!";

while(<INFILE>)
{
  if (/eau\n/) {print OUTFILE "$_"};
}

close INFILE;
close OUTFILE;


génère le fichier de sortie désiré. Cependant, ce programme n'enlève pas les mots dans le fichier entree.txt.

Je voudrais savoir quelles lignes de commandes je dois ajouter pour obtenir le fichier d'entrée modifié.

Merci
A voir également:

3 réponses

jee pee Messages postés 39606 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 22 avril 2024 9 230
Modifié le 16 mai 2019 à 16:47
Bonjour,

ce programme n'enlève pas les mots dans le fichier entree.txt : oui normal, le programme lit le fichier entree.txt et réécrit les termes non supprimés dans le fichier sortie.txt.

Tu n'as qu'à créer un nouveau fichier sortie2.txt qui reprend les termes non repris dans sortie.txt

2
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7
16 mai 2019 à 17:34
Salut,

Est-ce que cela fonctionnerait?

#!/usr/bin/perl

open(INFILE, "entree.txt") or die "Le fichier ne s'ouvre pas: $!";
open(OUTFILE, ">sortie.txt") or die "Le fichier ne s'ouvre pas: $!";
open(OUTFILE2, ">sortie2.txt") or die "Le fichier ne s'ouvre pas: $!";


while(<INFILE>)
{
  if (/eau\n/) {print OUTFILE "$_"}
  else {print OUTFILE2 "$_"};
}

close INFILE;
close OUTFILE;
close OUTFILE2;


Je ne sais pas si je peux changer le nom de OUTFILE. Est-ce un mot réservé du langage ou simplement le nom d'un pointeur?

Je ne peux l'essayer tout de suite car je n'ai pas mon ordinateur avec moi.

Merci
0
jee pee Messages postés 39606 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 22 avril 2024 9 230 > artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024
16 mai 2019 à 17:42
Oui c'est d'un code comme celui là dont je parlais.

Je ne programme pas en perl, mais suivant cette page : https://www.tutorialspoint.com/perl/perl_files.htm OUTFILE n'est pas un nom du langage, tu pourrais utiliser une autre valeur.
0
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7
16 mai 2019 à 17:52
En principe, ça devrait marcher. Je vais revenir plus tard pour commenter le résultat. Merci beaucoup.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 17 mai 2019 à 13:24
Salut artagon7,

Le code tel que tu l'as corrigé devrait "fonctionner", cependant voilà quelques remarques.

Une regexp qui matche à partir de la fin de ligne devrait utiliser le point d'ancrage $, donc quelque chose comme
if (/eau$/)
au lieu de
if (/eau\n/)
, à moins que tu veuilles tester quelque chose de particulier.

Sur les fichiers, la syntaxe que tu utilises, qui utilise des descripteurs qui sont des identifiants globaux était celle préconisée par le langage Perl avant la sortie de Perl 5.6 en 2000, avec la syntaxe à 2 paramètres de open.

Pour l'ouverture et l'écriture de fichiers en Perl moderne, tu devrais lire cet article, qui est bien fait : https://perlmaven.com/open-files-in-the-old-way ces pratiques, toujours supportées par Perl, pouvant poser différents types de problèmes expliqués par l'auteur.

Malheureusement, il y a beaucoup de code qui traîne des copier-coller de pratiques obsolètes, et même de tutoriels en ligne (y compris celui sur tutorialspoint.com), ou de cours, qui enseignent du code de ce type.

https://perldoc.perl.org/functions/open est la documentation officielle

Tu devrais prendre l'habitude de faire tes programmes Perl avec les directives
use strict;
et
use warnings;
:

#!/usr/bin/perl

use strict;
use warnings;  

et terminer toutes tes lignes avec un point-virgule, même celles précédant immédiatement une accolade, afin d'éviter, qu'en ajoutant du code au contenu de l'accolade, tu te retrouves avec une erreur de syntaxe sur une ligne qui avant fonctionnait parfaitement.

Dal
1
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7
17 mai 2019 à 18:16
Salut,

Concernant, la remarque que tu as faite :

Une regexp qui matche à partir de la fin de ligne devrait utiliser le point d'ancrage $, donc quelque chose comme
if (/eau$/)
 au lieu de 
if(/eau\n/)

, à moins que tu veuilles tester quelque chose de particulier.

Je voulais regrouper dans un fichier les mots qui ont la même terminaison. Si je ne mets pas le caractère qui indique la fin de la ligne \n, il va insérer dans le fichier des mots qui possèdent la chaîne de caractères mais qui n’est pas à la fin du mot.

Par exemple, pour la chaîne "eau", et le fichier d’entrée suivant :

bateau
beauté
chameau

le programme va ajouter le mot beauté au fichier de sortie :

bateau
beauté
chameau

alors que le résultat désiré est

bateau
chameau

Merci pour tes conseils. Effectivement, j'ai vu dans plusieurs exemples l'emploi des lignes :

use strict;
use warnings;


Dorénavant, je vais ajouter ces deux lignes. Tant qu’à faire les choses, mieux vaut les faire correctement.

Aussi, merci pour les liens.

Je programme rarement en Perl ou en tout autre langage. Je m’y connais très peu. Cependant, Perl s’est avéré très utile pour la tâche que je voulais faire.

Je vais mettre à jour mes notes sur Perl. Encore merci.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 17 mai 2019 à 18:57
De rien, Perl est très pratique et puissant pour traiter du texte :-)

Pour clarifier,
$
dans une regexp permet d'ancrer l'expression à la fin de la chaîne, indépendamment des caractères utilisés par le format de fichier texte sur tel ou tel système pour indiquer un retour à la ligne.

if (/eau$/)
réalise donc ce que tu veux, sans que tu aies à préciser un caractère de retour à la ligne, et signifie "matche la suite de caractères 'eau' à partir de la fin".

Un autre point d'ancrage utilisable avec les regexp est
^
, qui signifie le début de la chaîne.

Ainsi, avec ta liste une regexp comme
/^ch/
appliquée sur les lignes :

automne
bateau
brise
chameau
cheval
gâteau

permettrait de matcher les lignes commençant par les lettres "ch" :

chameau
cheval

Pour plus d'infos, le tutoriel officiel de Perl est : https://perldoc.perl.org/perlretut

Dal
0
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7
17 mai 2019 à 20:30
Tu écris : Perl est très pratique et puissant pour traiter du texte

Je m'en étais rendu compte! ;-)

Je vais télécharger les tutos sur le site officiel que tu as donné comme référence. Je vais être à jour. Merci
0
artagon7 Messages postés 415 Date d'inscription dimanche 6 novembre 2005 Statut Membre Dernière intervention 11 février 2024 7
23 mai 2019 à 17:03
Bonjour,

Comme tu l'as mentionné dans le message précédent, le caractère $ seul, permet d'ancrer l'expression à la fin de la chaîne. Il devient inutile d'ajouter les caractères symbolisant le retour de ligne à la fin.

Voici le code complet pour ce petit programme :

#!/usr/bin/perl

use strict;
use warnings;

open(FICHIER_ENTREE, "entree.txt") or die "Le fichier ne s'ouvre pas: $!";
open(FICHIER_SORTIE, ">>sortie.txt") or die "Le fichier ne s'ouvre pas: $!";
open(FICHIER_ENTREE_MODIFIEE, ">>entree_modifiee.txt") or die "Le fichier ne s'ouvre pas: $!";

while(<FICHIER_ENTREE>)
{
if (/eau$/) {print FICHIER_SORTIE "$_"}
else {print FICHIER_ENTREE_MODIFIEE "$_"};
}

close FICHIER_ENTREE;
close FICHIER_SORTIE;
close FICHIER_ENTREE_MODIFIEE;
0