【问题标题】:Finding pipe and redirects in perl @ARGV在 perl @ARGV 中查找管道和重定向
【发布时间】:2011-09-17 12:50:13
【问题描述】:

在编写传统的 Unix/Linux 程序时,perl 提供了菱形运算符 。我正在尝试了解如何测试是否根本没有传递任何参数,以避免 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

有没有更好的测试来查找shell传递给perl的所有命令行参数?

【问题讨论】:

  • 这是一个旁白,但当你可以写if (@array == 0)unless (@array) 时,千万不要写if ($#array &lt; 0)。当你想要“数组中元素的数量”时使用“数组中的最后一个索引”并不是你的意思。
  • 我会记住这一点

标签: perl pipe argv diamond-operator


【解决方案1】:

您可以使用file test operator -t 检查文件句柄 STDIN 是否对 TTY 开放。

因此,如果它对终端开放并且没有参数,那么您将显示使用文本。

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

【讨论】:

  • 感谢测试,了解如何访问 shell 命令行
  • 不客气。除了从@ARGV 读取参数之外,我认为您无法访问命令行。
  • 您的 Perl 程序在查看其参数时,在管道之前或重定向运算符之后看不到任何内容。 shell 解析它们并将它们连接到文件描述符以供您的程序访问。请参阅this Perlmonks thread,了解您的程序如何确定这些文件描述符连接到什么。长话短说:它依赖于平台,您最好的选择可能是使用lsof 程序。
  • 谢谢,我会看看,因为在管道和重定向中使用 的副作用是,如果 @ARGV 为空,菱形运算符会用“-”替换文件名 ($ARGV) , 并且知道实际文件名可能很重要,具体取决于脚本目的。
  • @Debinix,你为什么要命令行?为什么认为启动程序时甚至涉及到 bash 命令行?如果有的话,你认为通过命令行知道它有什么价值?
【解决方案2】:

使用 -t 运算符检查 STDIN 是否连接到 tty 当你使用管道或shell重定向时,它会返回false,所以你使用

if ( -t STDIN and not @ARGV ){ exit Usage(); }

【讨论】:

  • -1:这只是重复了 Oleg Pavliv 之前回答的一部分。
猜你喜欢
  • 2012-06-12
  • 2019-11-11
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
相关资源
最近更新 更多