(débutante) cut

cut (débutante) - Perl - Programmation

Marsh Posté le 15-06-2006 à 21:21:56    

Bonjour,
 
Je cherche à faire un petit script en PERL qui lira l'entree standard et delimitera celle-ci en colonnes  
avec comme caractere separateur l'espace. On prend en parametre la liste des colonnes à afficher.
 
Pour exemple quand je lance :
$>cat -e file_test | mon_script.pl 1 7 3 5
Je veux afficher :
les colonnes 1 3 5 et 7 du fichier file_test  (les colonnes sont uniquement compossés de chiffres en dur séparés par un espace)
 
Je ne sais pas par où commencer ?
 
Des idées ?
 
MERCI de m'éclairer ...


Message édité par mayapour le 15-06-2006 à 21:32:17
Reply

Marsh Posté le 15-06-2006 à 21:21:56   

Reply

Marsh Posté le 15-06-2006 à 21:42:13    

pour commencer, essaye de récupérer les paramètres passé par la ligne de commande (indice : faire des recherches sur le mot clé STDIN)

Reply

Marsh Posté le 15-06-2006 à 22:33:32    

Désolé, mauvais manip, message en double.
 
lami20j


Message édité par lami20j le 15-06-2006 à 22:39:44
Reply

Marsh Posté le 15-06-2006 à 22:38:11    

Salut,
 
Voilà un exemple en utilisant le fichier /etc/passwd ( le séparateur sera : )
Tu n'as qu'à remplacer : avec \s
1. avec handle F_LIRE

Code :
  1. #!/usr/bin/perl
  2. #
  3. use warnings;use strict;
  4. open F_LIRE,"/etc/passwd"
  5.         or die "E/S : $!\n";
  6. my @file;
  7. while (<F_LIRE> ){
  8.         push @file, [split /:/,$_ ];
  9. }
  10. foreach (@file){
  11.         print "@$_[@ARGV]\n";
  12. }

Résultat

Code :
  1. lami20j@debian:~/bin/my_deb_perl$ ./dvz_cut.pl 0 2 3
  2. root 0 0
  3. daemon 1 1
  4. bin 2 2
  5. sys 3 3
  6. sync 4 65534
  7. games 5 60
  8. man 6 12
  9. lp 7 7
  10. mail 8 8
  11. news 9 9
  12. uucp 10 10
  13. proxy 13 13
  14. www-data 33 33
  15. backup 34 34
  16. list 38 38
  17. irc 39 39
  18. gnats 41 41
  19. nobody 65534 65534
  20. Debian-exim 102 102
  21. lami20j 1000 1000
  22. messagebus 100 103
  23. hal 104 104
  24. sshd 101 65534
  25. vdr 103 106
  26. ubucorgeon 1001 1001


2. ce que tu demandes (avec cat)

Code :
  1. #!/usr/bin/perl
  2. #
  3. use warnings;use strict;
  4. my @file;
  5. my @col = @ARGV;
  6. @ARGV=();
  7. while (<> ){
  8.         push @file, [split /:/,$_ ];
  9. }
  10. foreach (@file){
  11.         print "@$_[@col]";
  12. }

Le résultat

Code :
  1. lami20j@debian:~/bin/my_deb_perl$ cat -e /etc/passwd | ./dvz_cut2.pl 0 2 6
  2. root 0 /bin/bash$
  3. daemon 1 /bin/sh$
  4. bin 2 /bin/sh$
  5. sys 3 /bin/sh$
  6. sync 4 /bin/sync$
  7. games 5 /bin/sh$
  8. man 6 /bin/sh$
  9. lp 7 /bin/sh$
  10. mail 8 /bin/sh$
  11. news 9 /bin/sh$
  12. uucp 10 /bin/sh$
  13. proxy 13 /bin/sh$
  14. www-data 33 /bin/sh$
  15. backup 34 /bin/sh$
  16. list 38 /bin/sh$
  17. irc 39 /bin/sh$
  18. gnats 41 /bin/sh$
  19. nobody 65534 /bin/sh$
  20. Debian-exim 102 /bin/false$
  21. lami20j 1000 /bin/bash$
  22. messagebus 100 /bin/false$
  23. hal 104 /bin/false$
  24. sshd 101 /bin/false$
  25. vdr 103 /bin/false$
  26. ubucorgeon 1001 /bin/bash$

lami20j


Message édité par lami20j le 15-06-2006 à 22:49:16
Reply

Marsh Posté le 15-06-2006 à 22:48:05    

Re,
 
à la place de

Code :
  1. my @col = @ARGV;
  2. @ARGV=();

on peut écrire

Code :
  1. my @col = splice(@ARGV,0,@ARGV);

lami20j

Reply

Marsh Posté le 15-06-2006 à 23:00:58    

MERCI pour tes réponses :
Mais avec cat -e file_test | ./mon_script.pl 1 2 6
J'obtient :
use: Command not found.
use: Command not found.
my: Command not found.
Badly placed ()'s.

Reply

Marsh Posté le 15-06-2006 à 23:12:23    

Re,

mayapour a écrit :

MERCI pour tes réponses :
Mais avec cat -e file_test | ./mon_script.pl 1 2 6
J'obtient :  
use: Command not found.
use: Command not found.
my: Command not found.
Badly placed ()'s.

tu peux afficher ici ton fichier? aussi le code que tu as écrit?
 
Pour voir où se trouve l'erreur.Merci.
 
lami20j

Reply

Marsh Posté le 15-06-2006 à 23:16:09    

Monfichier file_test :
a1 a2 a3 a4 a5 a6
b1 b2 b3 b4 b5 b6 b7 b8 b9
c1 c2 c3 c4
d1 d2 d3 d4 d5 d6 d7 d8 d9
e1 e2
 
Mon code (enfin le tien;-)):
#!/usr/pkg/bin/perl -w
 
@col = splice(@ARGV,0,@ARGV);      
 
while (<> ){
 
       push @file, [split /:/,$_ ];
 
      }
 
   foreach (@file){
 
       print "@$_[@col]";
}
 
Avec la commande cat -e file_test | ./mon_script.pl 1 2 6
J'obient maintenant : Badly placed ()'s.

Reply

Marsh Posté le 15-06-2006 à 23:27:17    

Re,
 
tu n'as pas remplacer les deux-points : avec un espace \s
 
Ensuite le problème se complique un peu vu que les chaines n'ont pas le même nombre de termes separés par un espace.
 
Donc tu auras des messages d'erreurs concerntant l'initialisation des valeurs.
 
lami20j

Reply

Marsh Posté le 15-06-2006 à 23:27:47    

toujours des mauvaises manipulations :(


Message édité par lami20j le 15-06-2006 à 23:28:48
Reply

Marsh Posté le 15-06-2006 à 23:27:47   

Reply

Marsh Posté le 15-06-2006 à 23:31:14    

J'ai remplacé les deux points par \s
Mais effectivement pas mieux :/


Message édité par mayapour le 15-06-2006 à 23:31:33
Reply

Marsh Posté le 16-06-2006 à 00:03:00    

Re,
 
essaie ça. Ce n'est pas excellent(j'ai enlevé l'option -w pour ne pas voir les messages d'erreurs)
Il y a un antislash avant le s dans la regex de split

Code :
  1. #!/usr/bin/perl
  2. #
  3. @col = splice(@ARGV,0,@ARGV);
  4. while (<> ){
  5.      push @file, [split /\s/,$_ ];
  6. }
  7. foreach (@file){
  8.     print "@$_[@col]\n";
  9. }

Chez moi ça marche

Code :
  1. lami20j@debian:~/bin/my_deb_perl$ cat maya
  2. a1 a2 a3 a4 a5 a6
  3. b1 b2 b3 b4 b5 b6 b7 b8 b9
  4. c1 c2 c3 c4
  5. d1 d2 d3 d4 d5 d6 d7 d8 d9
  6. e1 e2
  7. lami20j@debian:~/bin/my_deb_perl$ cat maya | ./dvz_cut3.pl 1 2 6
  8. a2 a3
  9. b2 b3 b7
  10. c2 c3
  11. d2 d3 d7
  12. e2
  13. lami20j@debian:~/bin/my_deb_perl$

lami20j


Message édité par lami20j le 16-06-2006 à 00:08:13
Reply

Marsh Posté le 16-06-2006 à 00:03:54    

toujours en double  :(  j'arrête pour ce soir. bonne continuation. lami20j


Message édité par lami20j le 16-06-2006 à 00:07:29
Reply

Marsh Posté le 16-06-2006 à 00:09:55    

Je ne comprend pas pourquoi : idem
Badly placed ()'s.
 
???
 
MERCI pour cette solution qui me semble devoir fontionner ;-)

Reply

Marsh Posté le 16-06-2006 à 09:27:06    

Salut,

mayapour a écrit :

Je ne comprend pas pourquoi : idem
Badly placed ()'s.
 
???
 
MERCI pour cette solution qui me semble devoir fontionner ;-)


Essaie d'exécuter avec

Code :
  1. cat -e file_test | perl ./mon_script.pl 1 2 6


 
Pour ton erreur  
 
Badly placed ()'s
 
(A) Vous lancez accidentellement votre script par csh au lieu de Perl. Vérifiez la ligne avec #!, ou lancez votre script manuellement dans Perl.  
 
(A) Erreur externe (non générée par Perl).
 
Ca pourra te servir à l'avenir :
http://perl.enstimac.fr/DocFr/perldiag.html
 
lami20j


Message édité par lami20j le 16-06-2006 à 09:28:48
Reply

Marsh Posté le 16-06-2006 à 12:07:03    

Re,
 
Peut être je devrais le devrait le faire de début pour comprendre ce que j’ai fait. Mea culpa.

Code :
  1. while (<> ){
  2.   push @file, [split /s/,$_ ];
  3. }


 
while (<> ) va lire la sortie de cat fichier et dans la boucle je stocke dans un tableau des tableaux les éléments dont le séparateur est l’espace.

Code :
  1. @col = splice(@ARGV,0,@ARGV);


Cette ligne stocke dans @col les arguments et vide @ARGV.
Pourquoi ?  
Puisque la boucle while(<> ) lit dans @ARGV et comme 2, 3 et 4 ne sont pas des fichiers une exception sera levée.  
Une fois @ARGV vide <> va lire seulement depuis pipe |

Code :
  1. foreach (@file){
  2.   print "@$_[@col]\n";
  3. }


Pour affichage on va utiliser une tranche de tableau.
Comme @col contient les arguments 2, 4 et 6 par exemple je vais afficher pour chaque élément (qui est un tableau anonyme) du @file, uniquement les éléments 2, 4 et 6 qui correspondent à la colonne 3, 5 et 7 de ton fichier.  
En suivant cet algo (à savoir que ce n’est pas le meilleur et en plus quand on est en Perl il ne faut pas oublier TMTOWTDI – There’s More Than One Way To Do It – Il y a plusieurs façon de le faire) tu peux écrire toi-même le code ainsi tu comprendras mieux et tu éviteras aussi les erreurs de syntaxe.
 
A savoir que tu auras toujours des messages Warning si les lignes de ton fichier ne contiennent pas le même nombre d’éléments. Donc peut être il faut une autre approche pour traiter ça.
Un warning n’est pas forcément une erreur mais une information.
Si tu enlèves –w ou use warnings tu n’auras pas les messages warnings. A toi de voir.
Je vais penser pour une autre approche.
Par exemple tu peux utiliser la commande cut dant ton script (voir man cut). Tu peux le faire avec la fonctin system  
(voir dans la doc - http://perl.enstimac.fr/DocFr/perl [...] em_system)
Si tu ne comprends pas, fait un signe. Merci.
 
lami20j


Message édité par lami20j le 16-06-2006 à 12:28:03
Reply

Marsh Posté le 19-06-2006 à 17:45:08    

Merci pour toute ton aide lami20j !

Reply

Sujets relatifs:

Leave a Replay

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