2013-05-22 16 views
5

Ho scritto un programma perl per prendere un'espressione regolare dalla riga di comando e fare una ricerca ricorsiva della directory corrente per certi nomi di file e file, grep ognuno per la regex, e produrre i risultati, inclusi nome file e numero di riga. [Grep base + trovare la funzionalità che posso entrare e personalizzare in base alle esigenze]

cat <<'EOF' >perlgrep2.pl 
#!/usr/bin/env perl 
$expr = join ' ', @ARGV; 

my @filetypes = qw(cpp c h m txt log idl java pl csv); 
my @filenames = qw(Makefile); 

my $find="find . "; 
my $nfirst = 0; 
foreach(@filenames) { 
    $find .= " -o " if $nfirst++; 
    $find .= "-name \"$_\""; 
} 
foreach(@filetypes) { 
    $find .= " -o " if $nfirst++; 
    $find .= "-name \\*.$_"; 
} 

@files=`$find`; 

foreach(@files) { 
    s#^\./##; 
    chomp; 
} 

@ARGV = @files; 

foreach(<>) { 
    print "$ARGV($.): $_" if m/\Q$expr/; 
    close ARGV if eof; 
} 
EOF 

cat <<'EOF' >a.pl 
print "hello "; 
$a=1; 
print "there"; 
EOF 

cat <<'EOF' >b.pl 
print "goodbye "; 
print "all"; 
$a=1; 
EOF 

chmod ugo+x perlgrep2.pl 
./perlgrep2.pl print 

Se si copia e incolla questo nel vostro terminale, si vedrà questo:

perlgrep2.pl(36): print "hello "; 
perlgrep2.pl(0): print "there"; 
perlgrep2.pl(0): print "goodbye "; 
perlgrep2.pl(0): print "all"; 
perlgrep2.pl(0):  print "$ARGV($.): $_" if m/\Q$expr/; 

Questo è molto sorprendente me. Il programma sembra funzionare tranne che il $. e le variabili $ ARGV non hanno i valori che mi aspettavo. Appare dallo stato delle variabili che perl ha già letto tutti e tre i file (totale di 36 linee) quando esegue la prima iterazione del ciclo su <>. Cosa sta succedendo ? Come risolvere ? Questo è Perl 5.12.4.

risposta

10

Si sta utilizzando foreach(<>) dove si dovrebbe usare while(<>). foreach(<>) leggerà tutti i file in @ARGV in un elenco temporaneo prima di inizia a scorrere su di esso.

+0

Grazie! Devo dire che di recente ho letto molta documentazione perl e non l'ho capito. – Colin

+0

Ah, quindi "for" valuta <> nel contesto dell'elenco, che legge l'intero file (s) in una lista, e mentre valuta <> in un contesto scalare che legge la riga successiva. – Colin

+0

@Colin è giusto. – hobbs