2011-09-07 6 views
1

Je lis le contenu du fichier en Perl par le code suivantComment ajouter un numéro d'incrémentation automatique à un tableau?

my @files = glob("$PATH/*"); 
foreach my $file (@files){ 
    open(MYFILE,"<$file"); 
    my @fileContent = <MYFILE>; 
    close(MYFILE); 
} 

Maintenant, je veux préfixer numéro auto-incrémentée à chaque ligne. Quelque chose comme -

fileContent[0] = 1: This 
fileContent[1] = 2: is 
fileContent[2] = 3: a 
fileContent[3] = 4: text 
fileContent[4] = 5: file. 

Quelqu'un sait un moyen efficace de le faire?

Merci!

Répondre

10

Que diriez-vous d'un one-liner?

perl -wne 'print "$.: $_"; close ARGV if eof;' path/* 

ou à l'intérieur d'un script, avec un tableau:

use strict; 
use warnings; 
use autodie; 

while (<tmp/data*>) { 
    open my $fh, '<', $_; 
    my @fileContent; 
    push @fileContent, "$.: $_" while <$fh>; 
} 

Documentation sur $.here.

+2

Vous pouvez également utiliser ['sprintf'] (http://perldoc.perl.org/functions/sprintf.html) si vous devez formater nombre (par exemple, à une certaine largeur), et je vous recommande de vérifier [perlvar] (http://perldoc.perl.org/perlvar.html) pour plus d'informations sur '$ .'. –

+0

Merci pour la réponse! Le scénario me convient le mieux! :) –

+0

@Rah Vous êtes les bienvenus. – TLP

0

Essayez ceci pour votre ligne d'affectation:

my $i; 
my @fileContent = map{++$i.": $_"} (<MYFILE>) 
+0

Cela peut être un peu lent sur de gros fichiers, mais peut facilement être transformé en une boucle 'for' pour surmonter ce problème. –

+0

Hey! Ça a l'air sympa mais de quelle taille parle-t-on? –

+0

Grand en termes informatiques. Grand comme dedans, prend beaucoup de temps pour charger tout du disque ou ne peut pas être lu dans la mémoire. –

0

efficace? Je ne sais pas qu'il y a vraiment un inefficace façon de le faire (sauf si vous le rendre inefficace exprès).

for my $lineNumber ([email protected]) { 
    substr($fileContent[$lineNumber-1], 0, 0, "$lineNumber: "); 
} 
+0

Merci pour la suggestion, mais je pensais que le bouclage serait une façon inefficace de le faire comme il le fait pour plusieurs fichiers et chaque fichier a des centaines/milliers de lignes. –

+2

Une boucle 'for' est probablement le moyen le plus rapide de le faire. Et c'est aussi rapide. Faire des centaines de fichiers et chacun a des centaines ou des milliers de lignes ne prendra pas plus d'une minute. Vous pouvez utiliser la fonction Perl 'map'. C'est plus court car il faut une ligne de code, c'est plus cool aussi parce que quand on l'utilise, les filles se pâment _ "Oh, il est tellement chaud! Il sait comment utiliser la commande" map "de Perl. plus lent qu'une boucle 'for' –

+2

@David Toutes les filles cool * disent * ça, c'est connu, mais" while "peut être préférable en ce qui concerne l'utilisation de la mémoire – TLP

0

Voici votre code, sous la direction d'utiliser des variables lexicales, 3 arg ouvertes, et une déclaration de carte pour ajouter les numéros de ligne.

my @files = glob("$PATH/*"); 
foreach my $file (@files){ 
    open my $fh,'<', $file or die $!; 
    my $i = 1; 
    my @fileContent = map {$i++.": $_"} <$fh>; 

    # do something with @fileContent 
} 

Voici un exemple qui est un peu plus perlienne (en utilisant plus des fonctions automatiques):

for (<$PATH/*>) { 
    local @ARGV = $_; 
    my $i = 1; 
    my @lines = map {$i++.": $_"} <>; 

    # do something with @lines 
} 

Et voici un exemple qui utilise $. (la ligne d'entrée numérique) et une boucle while pour lire le fichier ligne par ligne.

for (<$PATH/*>) { 
    local (@ARGV, $_) = $_; 
    my @lines; 
    push @lines, "$.: $_" while <>; 

    # do something with @lines 
} 
+0

J'ai fait un test rapide et les chiffres réinitialisés au moins avec perl 5.12 –

+0

Nevermind, mon erreur. Vous utilisez un nouveau @ARGV pour chaque fichier. – TLP

0

Changer votre ouverture à:

open MYFILE, '-|', 'grep', '-n', '', $file 
Questions connexes