A fellow Stackoverflower tried to use @ARGV
in his END
block but was unable to.
Why is it that @ARGV
is only defined inside the BEGIN
block with the following one-liner:
$ perl -lne 'BEGIN{ print "BEGIN" if @ARGV }
print "MIDDLE" if @ARGV }
{ print "END" if @ARGV ' file
BEGIN
perldoc perlrun
doesn't shed any light on the matter. What's going on here?
First, arrays cannot be undefined. You are checking if the array is empty. To understand why it's being emptied, you need to understand -n
. -n
surrounds your code with
LINE: while (<>) {
...
}
which is short for
LINE: while (defined($_ = <ARGV>)) {
...
}
ARGV
is a magical handle that reads through the files listed in @ARGV
, shifting out the file names as it opens them.
$ echo foo1 > foo
$ echo foo2 >>foo
$ echo bar1 > bar
$ echo bar2 >>bar
$ echo baz1 > baz
$ echo baz2 >>baz
$ perl -nlE'
BEGIN { say "Files to read: @ARGV" }
say "Read $_ from $ARGV. Files left to read: @ARGV";
' foo bar baz
Files to read: foo bar baz
Read foo1 from foo. Files left to read: bar baz
Read foo2 from foo. Files left to read: bar baz
Read bar1 from bar. Files left to read: baz
Read bar2 from bar. Files left to read: baz
Read baz1 from baz. Files left to read:
Read baz2 from baz. Files left to read:
Keep in mind that BEGIN
blocks are executed as soon as they are compiled, so the <ARGV>
hasn't yet been executed when the BEGIN
block is being executed (even though it appears earlier in the program), so @ARGV
hasn't been modified yet.
-n
is documented in perlrun. ARGV
, @ARGV
and $ARGV
are documented in perlvar.
A BEGIN block runs before anything else. At that point, @ARGV has everything being passed and a test for non-emptiness returns true. When the END block runs, the elements of the original @ARGV have been shifted away by the implicit while(<>) {...} loop generated by the '-n' switch. Since there is nothing left, the empty @ARGV tests false. Change the END block to:
{print "END" if defined @ARGV}
As each element of @ARGV is shifted, it is stored in $ARGV. Hence, the block could be also rewritten:
{print "END" if $ARGV}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With