Soucis concaténation

Soucis concaténation - Perl - Programmation

Marsh Posté le 24-07-2013 à 15:09:55    

Hello,
 
J'ai un fichier texte comme ceci :
 

Citation :

bla1
bla2
bla3


 
J'aimerais exécuter une commande prenant en variable chaque item.
 
Voici mon taff pour l'instant :
 

Code :
  1. #!/usr/bin/env perl -w
  2. my $liste_hotes = "/mnt/250Go/Taff/BackupPC/Archivage/hosts.txt";
  3. my $date = `date +%d%m%y`;
  4. my @array;
  5. open(my $FICHIER_HOST,"< $liste_hotes" ) || die ("Impossible d'ouvrir le fichier : $!" );
  6. while (<$FICHIER_HOST> ) {
  7. $_ =~ s/\s+$//;
  8. chomp($_);
  9. push (@array, $_);
  10. }
  11. for my $i (@array) {
  12. print $i.'.'. $date.'.tar.gz';
  13. print "\n";
  14. }
  15. close $FICHIER_HOST;


 
J'obtiens ça comme résultat :

Citation :

bla1.240713
.tar.gz
bla2.240713
.tar.gz
bla3.240713
.tar.gz


 
Alors que j'aimerais ceci :

Citation :

bla1.240713.tar.gz
bla2.240713.tar.gz
bla3.240713.tar.gz


 
Et je ne comprend pas bien pourquoi...
 
Précision: je débute en Perl, désolé si je choque quelqu'un  :o


---------------
Je suis pas Superman, je suis Super-vagabond, mais toi t’es Super-pomme. Tu es très gouteuse, tu es très... biologique, très naturelle ! Tu es la pomme de ma vie.
Reply

Marsh Posté le 24-07-2013 à 15:09:55   

Reply

Marsh Posté le 24-07-2013 à 16:27:15    

Manifestement, la ligne my $date = `date +%d%m%y`; renvoie une valeur terminée par un "\n"
Plutôt que faire un appel au shell, utilisez directement les fonctions perl comme localtime
my $date = join "", map { sprintf("%02d", ($_ + (0, 1, -100)[$i++])) }(localtime)[3..5];
devrait faire l'affaire.
 
Explication de cette ligne  
Je pars de localtime
ça renvoie une liste qu'on peut récupérer ainsi:  
my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime() ;
ce qui nous intéresse ici, c'est $mday, $mon, $year
que je récupère directement comme sous liste: (localtime)[3..5];
problème: c'est décalé:
pour les jours, c'est OK, mais pour les mois, ça commence à 0 pour janvier, et pour les années, 0 c'est 1900.
Il faut donc décaler les valeurs:
my ( $mday, $mon, $year ) = (localtime)[3..5];
$mon += 1;
$year += 1900;
En perl, on peut faire travailler directement sur la liste, en faisant
my ( $mday, $mon, $year ) = map {$_ + (0, 1, 1900)[$i++]}(localtime)[3..5];
Comme dans votre cas on veut que la partie de l'année a partir de 2000, au lieu d'ajouter 1900, on va retirer 100
my ( $mday, $mon, $year ) = map {$_ + (0, 1, -100)[$i++]}(localtime)[3..5];
On veut de plus que chaque valeur soit sur deux chiffres, avec un 0 initial si nécessaire, on fait alors
my ( $mday, $mon, $year ) = map { sprintf("%02d", $_ + (0, 1, -100)[$i++])}(localtime)[3..5];
Enfin, on concatène la liste dans une variable
my $date = join "", map { sprintf("%02d", $_ + (0, 1, -100)[$i++])}(localtime)[3..5];
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 24-07-2013 à 17:18:57    

Une réécriture de votre code:
 

Code :
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. my $liste_hotes = '/mnt/250Go/Taff/BackupPC/Archivage/hosts.txt';
  7.  
  8. open my $FICHIER_HOST, '<', $liste_hotes;
  9. my @array = <$FICHIER_HOST>;
  10. close $FICHIER_HOST;
  11.  
  12. map {s/\s+$//} @array;
  13.  
  14. my $i = 0;
  15. my $date = join '', map { sprintf("%02d", $_ + (0, 1, -100)[$i++]) }(localtime)[3..5];
  16.  
  17. foreach (@array) {
  18.  print $_.'.'. $date.".tar.gz\n";
  19. }


 
#!/usr/bin/env perl -w
plutôt que le flag -w, utilisez
use strict;
use warnings;
 
et le use autodie; permet d'éviter les open(my $FICHIER_HOST,"< $liste_hotes" ) || die ("Impossible d'ouvrir le fichier : $!" );
 
my $liste_hotes = "/mnt/250Go/Taff/BackupPC/Archivage/hosts.txt"; -> my $liste_hotes = '/mnt/250Go/Taff/BackupPC/Archivage/hosts.txt';
Toujours des simple quotes avec les paths et noms de fichiers, s'il n'y a rien de variable au milieu
 
my @array = <$FICHIER_HOST>; copie le contenu du fichier dans l'array
et map {s/\s+$//} @array; modifie en place l'array
C'est pas mieux que ce que vous aviez écrit, juste un peu plus lisible.
Le chomp est a priori inutile, car le s/\s+$// va virer le \n (et le cas échéant \r) de fin de ligne.  
 
A+,


Message édité par gilou le 24-07-2013 à 17:25:09

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 24-07-2013 à 17:22:12    

Super, merci, ton explication est parfaite.
 
J'ai obtenu cette erreur avec ton bout de code :
"Global symbol "$i" requires explicit package name".
 
Étant donné que j'utilise use strict; il a fallu que je mette un my $i; quelque part pour que tout fonctionne nickel.
Ah ben oui...je viens de le voir dans votre code. Initialiser la variable.
 
Encore merci pour ces conseils.  :hello:


Message édité par zit11 le 24-07-2013 à 17:25:08

---------------
Je suis pas Superman, je suis Super-vagabond, mais toi t’es Super-pomme. Tu es très gouteuse, tu es très... biologique, très naturelle ! Tu es la pomme de ma vie.
Reply

Marsh Posté le 24-07-2013 à 17:26:05    

En relisant le code, j'ai viré le chomp qui était en fait inutile.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed