Почему @ARGV не определено внутри этого однострочного Perl? - PullRequest
4 голосов
/ 02 января 2012

Парень из Stackoverflower пытался использовать @ARGV в своем блоке END, но не смог.

Почему @ARGV определяется только внутри блока BEGIN со следующим однострочником:

$ perl -lne 'BEGIN{ print "BEGIN"  if @ARGV }
                    print "MIDDLE" if @ARGV }
                  { print "END"    if @ARGV  ' file
  BEGIN

perldoc perlrun не проливает свет на этот вопрос. Что здесь происходит?

Ответы [ 2 ]

5 голосов
/ 03 января 2012

Во-первых, массивы не могут быть undefined . Вы проверяете, является ли массив пустым . Чтобы понять, почему его опорожняют, вам нужно понять -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 задокументировано в perlrun . ARGV, @ARGV и $ARGV задокументированы в perlvar .

4 голосов
/ 02 января 2012

Блок BEGIN запускается раньше всего.В этот момент у @ARGV есть все, что пройдено, и тест на непустоту возвращает true.Когда выполняется блок END, элементы исходного @ARGV были удалены неявным циклом while (<>) {...}, сгенерированным переключателем '-n'Поскольку ничего не осталось, пустой @ARGV проверяет false.Измените блок END на:

{print "END" if defined @ARGV}

Когда каждый элемент @ARGV сдвинут, он сохраняется в $ ARGV.Следовательно, блок также можно переписать:

{print "END" if $ARGV}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...