Поиск трубы и перенаправлений в 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.

Так что, если он открыт для терминала и нет аргументов, вы отображаете текст использования.

if ( -t STDIN and not @ARGV ) {
    # print usage and exit
}

Используйте оператор -t, чтобы проверить, подключен ли STDIN к tty, когда вы используете перенаправление канала или оболочки, он вернет false, поэтому вы используете

if ( -t STDIN and not @ARGV ){ exit Usage(); }
Другие вопросы по тегам