他的END
街区中的一个Stackoverflower tried to use @ARGV
,但无法进行。
为什么@ARGV
仅在BEGIN
块内定义,并带有以下单行:
$ perl -lne 'BEGIN{ print "BEGIN" if @ARGV }
print "MIDDLE" if @ARGV }
{ print "END" if @ARGV ' file
BEGIN
perldoc perlrun
没有说明这件事。这是怎么回事?
答案 0 :(得分:5)
首先,数组不能未定义。您正在检查数组是否为空。要了解它被清空的原因,您需要了解-n
。 -n
使用
LINE: while (<>) {
...
}
是
的缩写LINE: while (defined($_ = <ARGV>)) {
...
}
ARGV
是一个神奇的句柄,可以读取@ARGV
中列出的文件,在打开文件名时将其移出。
$ 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:
请记住,BEGIN
块一经编译就会执行,因此<ARGV>
块在执行BEGIN
块时尚未执行(即使它出现在程序的早期版本中),因此@ARGV
尚未修改。
-n
。 ARGV
中记录了@ARGV
,$ARGV
和{{1}}。
答案 1 :(得分:4)
BEGIN块先于其他任何方式运行。那时,@ ARGV已经传递了所有内容,并且非空虚的测试返回true。当END块运行时,原始@ARGV的元素已被'-n'开关生成的隐式while(&lt;&gt;){...}循环移走。由于没有任何东西,空的@ARGV测试为false。将END块更改为:
{print "END" if defined @ARGV}
当@ARGV的每个元素移位时,它存储在$ ARGV中。因此,该块也可以被重写:
{print "END" if $ARGV}