Lire et modifier un fichier en perl [Résolu/Fermé]

Messages postés
8
Date d'inscription
mardi 18 juin 2013
Statut
Membre
Dernière intervention
1 septembre 2017
- - Dernière réponse : [Dal]
Messages postés
5223
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
1 octobre 2019
- 4 sept. 2017 à 12:57
Bonjour,

Je souhaite lire et modifier un fichier en Perl.

Le fichier se présente de cette forme :

NAME1)
paragraphe 1
;;
NAME2)
paragraphe 2
# la ligne à modifier si mode active Yes sinon No
word='Yes'
;;
NAME3)
paragraphe 3
;;

Le script en perl
if ( $opt_target eq 'NAME2' ) {
my $file = "file.csv";
main->parse_file($file);
}

# Fonctions

sub parse_file {
my $class = shift;
my $file = shift;
my $inside = 0;
my @lines;

# RDWR : Lecture et ecriture du fichier
my $fh = IO::File->new($file, O_RDWR)
or $logger->logdie("open $file failed: $!");

# Decouper le fichier par bloc => paragraphe 2
while ( <$fh> ) {
chomp;
if (/NAME2/) {
$inside = 1;
@lines = ();
print "$_ \n";
}
push @lines, $_ if ($inside);
if (/;;/ and $inside) {
$inside = 0;
$class->modification_value($file, \@lines);
}
}
$fh->close;

return;
}

sub modification_value {
my $class = shift;
my $file = shift;
my $aref = shift;
my $value;
my $basename = basename($file);

my $i = 0;
while ($i > scalar @{ $aref }) {
if ($aref->[$i] =~ /word=(.+)/) {
$value = $1;
print "$value \n";
if ( $opt_mode eq 'activate' ) {
$aref->[$i] =~ s/$value/'Yes'/;
print "$aref->[$i] \n";
}
else
{
$aref->[$i] =~ s/$value/'No'/;
print "$aref->[$i] \n";
}
}
$i++;
}
return;
}

Le script me renvoie bien les bonnes valeurs mais le fichier n'est pas modifié. Je ne comprends pas pourquoi :-(

Je vous remercie d'avance pour votre aide et vos conseils.

Naba.
Afficher la suite 

1 réponse

Messages postés
5223
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
1 octobre 2019
802
0
Merci
Salut Naba,

Il y a plusieurs problèmes :

- tout d'abord, je ne comprends pas bien ton code, et je pense qu'il n'est pas complet
- tu n'utilises pas le filehandle $fh pour des opérations d'écriture, seulement de lecture
- je ne pense pas que tu puisses modifier un fichier texte en l'ouvrant ainsi, sans risquer un écrasement de données
- ton code pour parser et localiser les informations à changer est compliqué et une simple regexp sur le contenu du fichier suffirait à faire ce qu'il faut

à mon sens, il faut :

- ouvrir le fichier en lecture et en aspirer la totalité dans une variable
- appliquer une regexp pour modifier ce qui doit l'être
- écrire le contenu dans un fichier intermédiaire
- effacer le fichier d'origine et renommer le fichier temporaire

Voilà un exemple dont tu peux t'inspirer, qui utilise File::Temp et File::Copy, qui sont des modules standard de Perl, et qui fonctionne sur l'exemple de format que tu donnes :

#!/usr/bin/perl

use strict;
use warnings;

# simulate a value for $opt_mode
my $opt_mode = "deactivate";

# load na_ba85.txt into a string
my $string;
{
    local $/ = undef;
    open my $fh, "<", "na_ba85.txt" or die "could not open file: $!";
    $string = <$fh>;
    close $fh;
}

# use regexp to match the file in 3 parts
my $beg;    # beginning up to opening ' of matched word
my $end;    # rest from closing ' up to end
if ($string =~ /(.*^NAME2\).*?word=')([^']+)(.*)/sm) {
    $beg = $1;
    $end = $3
} else {
    print "Error: no match, wrong file format\n";
    exit;
}

# set $word according to value of $opt_mode
my $word;
if ($opt_mode eq "activate") {
    $word = "Yes";
} else {
    $word = "No";
}

# save to a temp file and replace na_ba85.txt
use File::Temp qw(tempdir);
my $dir = tempdir( CLEANUP => 1 );
open my $fh, ">", "$dir/na_ba85.txt";
print $fh $beg . $word . $end;
close $fh;
use File::Copy;
copy("$dir/na_ba85.txt", "na_ba85.txt") or die "Copy failed: $!"; 

Le répertoire temporaire et le fichier temporaire seront supprimés automatiquement par Perl.

Dal