Ответ 1
Переменная $ARGV
содержит текущий обрабатываемый файл.
$ echo hello1 > file1
$ echo hello2 > file2
$ echo hello3 > file3
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file*
file1:hello1
file2:hello2
file3:hello3
Perl предлагает эту очень приятную функцию:
while ( <> )
{
# do something
}
..., который позволяет использовать script как script.pl <filename>
, а также cat <filename> | script.pl
.
Теперь, есть ли способ определить, был ли вызов script первым, и если да, то какое имя файла было?
Я знаю, что знал это однажды, и знаю, что я даже использовал конструкцию, но я не могу вспомнить, где/как. И было очень сложно искать "сеть для этого" ( "perl stdin filename"? Нет...).
Помогите, пожалуйста?
Переменная $ARGV
содержит текущий обрабатываемый файл.
$ echo hello1 > file1
$ echo hello2 > file2
$ echo hello3 > file3
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file*
file1:hello1
file2:hello2
file3:hello3
раздел "Операторы ввода/вывода" perlop
очень информативен.
По существу, в первый раз <>
выполняется, -
добавляется к @ARGV
, если он запущен пустым. Открытие -
приводит к клонированию дескриптора файла STDIN
, а переменная $ARGV
устанавливается на текущий элемент @ARGV
по мере его обработки.
Здесь полный клип.
Нулевой дескриптор файла "< > " является особым: его можно использовать для эмуляции поведение sed и awk, а также любую другую программу фильтров Unix, которая принимает список имен файлов, делая то же самое для каждой строки ввода из всех их. Вход от "< > " поступает либо от стандартного ввода, либо от каждого файл, указанный в командной строке. Вот как это работает: в первый раз "< > " оценивается, массив @ARGV проверяется, и если он пуст, $ ARGV [0] установлен на "-", который при открытии дает вам стандартный ввод. Затем массив @ARGV обрабатывается как список имен файлов. Цикл
while (<>) { ... # code for each line }
эквивалентен следующему Perl-подобному псевдокоду:
unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } }
за исключением того, что это не так громоздко говорить, и на самом деле будет работать. Это действительно сдвигает массив @ARGV и помещает текущее имя файла в $ ARGV. Он также использует файл ARGV вручную. "< > " - это просто синоним "<ARGV> ", который является магическим. (Псевдокод выше не потому что он рассматривает "<ARGV> " как не магический.)
Если вам интересно узнать, когда <>
переключается на новый файл (например, в моем случае - я хотел записать новое имя файла и номер строки), eof() предлагает трюк:
# reset line numbering on each input file
while (<>) {
next if /^\s*#/; # skip comments
print "$.\t$_";
} continue {
close ARGV if eof; # Not eof()!
}