Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are Perl's $. and $ARGV behaving strangely after setting @ARGV and using <>

I wrote a perl program to take a regex from the command line and do a recursive search of the current directory for certain filenames and filetypes, grep each one for the regex, and output the results, including filename and line number. [ basic grep + find functionality that I can go in and customize as needed ]

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

If you copy and paste this into your terminal, you will see this:

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/;

This is very surprising to me. The program appears to be working except that the $. and $ARGV variables do not have the values I expected. It appears from the state of the variables that perl has already read all three files (total of 36 lines) when it executes the first iteration of the loop over <>. What's going on ? How to fix ? This is Perl 5.12.4.

like image 409
Colin Avatar asked May 22 '13 16:05

Colin


1 Answers

You're using foreach(<>) where you should be using while(<>). foreach(<>) will read every file in @ARGV into a temporary list before it starts iterating over it.

like image 111
hobbs Avatar answered Nov 23 '22 04:11

hobbs