Поиск трубы и перенаправлений в perl @ARGV
При написании традиционной программы для Unix/Linux perl предоставляет оператор diamond <>. Я пытаюсь понять, как проверить, не передано ли вообще никакого аргумента, чтобы избежать сценария perl, сидящего в цикле ожидания для STDIN, когда это не должно происходить.
#!/usr/bin/perl
# Reading @ARGV when pipe or redirect on the command line
use warnings;
use strict;
while ( defined (my $line = <ARGV>)) {
print "$ARGV: $. $line" if ($line =~ /eof/) ; # an example
close(ARGV) if eof;
}
sub usage {
print << "END_USAGE" ;
Usage:
$0 file
$0 < file
cat file | $0
END_USAGE
exit();
}
Несколько прогонов выходных данных показывают, что <> работает, но без аргументов мы задерживаем ввод STDIN, а это не то, что мне нужно.
$ cat grab.pl | ./grab.pl
-: 7 print "$ARGV: $. $line" if ($line =~ /eof/) ; # an example
-: 8 close(ARGV) if eof;
$ ./grab.pl < grab.pl
-: 7 print "$ARGV: $. $line" if ($line =~ /eof/) ; # an example
-: 8 close(ARGV) if eof;
$ ./grab.pl grab.pl
grab.pl: 7 print "$ARGV: $. $line" if ($line =~ /eof/) ; # an example
grab.pl: 8 close(ARGV) if eof;
$ ./grab.pl
^C
$ ./grab.pl
[Ctrl-D]
$
Первая мысль - протестировать $#ARGV, который содержит номер последнего аргумента в @ARGV. Затем я добавил тест в скрипт выше, перед циклом while, вот так:
if ( $#ARGV < 0 ) { # initiated to -1 by perl
usage();
}
Это не дало желаемых результатов. $#ARGV равно -1 для перенаправления и канала в командной строке. При выполнении этой проверки (grabchk.pl) проблема изменилась, и я не могу прочитать содержимое файла по <> в конвейере или в случаях перенаправления.
$ ./grabchk.pl grab.pl
grab.pl: 7 print "$ARGV: $. $line" if ($line =~ /eof/) ;
grab.pl: 8 close(ARGV) if eof;
$ ./grabchk.pl < grab.pl
Usage:
./grabchk.pl file
./grabchk.pl < file
cat file | ./grabchk.pl
$ cat grab.pl | ./grabchk.pl
Usage:
./grabchk.pl file
./grabchk.pl < file
cat file | ./grabchk.pl
Есть ли лучший тест, чтобы найти все параметры командной строки, переданные в Perl оболочкой?
2 ответа
Используйте оператор -t, чтобы проверить, подключен ли STDIN к tty, когда вы используете перенаправление канала или оболочки, он вернет false, поэтому вы используете
if ( -t STDIN and not @ARGV ){ exit Usage(); }