如何在不使用select的情况下检查(查看)Perl中的管道数据的STDIN?

时间:2022-05-16 20:37:44

I'm trying to handle the possibility that no arguments and no piped data is passed to a Perl script. I'm assuming that if there are no arguments then input is being piped via STDIN. However if the user provides no arguments and does not pipe anything to the script, it will try to get keyboard input. My objective is to provide an error message instead.

我正在尝试处理没有参数和管道数据传递给Perl脚本的可能性。我假设如果没有参数,则输入通过STDIN进行管道传输。但是,如果用户不提供任何参数并且不向脚本输送任何内容,它将尝试获取键盘输入。我的目标是提供错误消息。

Unfortunately, select() is not portable to some non-POSIX systems. Is there another way to do this with maximum portability?

不幸的是,select()不能移植到某些非POSIX系统。还有另一种方法可以实现最大的可移植性吗?

2 个解决方案

#1


Perl comes with the -t file-test operator, which tells you if a particular filehandle is open to a TTY. So, you should be able to do this:

Perl附带-t file-test运算符,它告诉您特定的文件句柄是否对TTY开放。所以,你应该能够做到这一点:

if ( -t STDIN and not @ARGV ) {
    # We're talking to a terminal, but have no command line arguments.
    # Complain loudly.
}
else {
    # We're either reading from a file or pipe, or we have arguments in
    # @ARGV to process.
}

A quick test reveals this working fine on Windows with Perl 5.10.0, and Linux with Perl 5.8.8, so it should be portable across the most common Perl environments.

快速测试表明,在Windows上使用Perl 5.10.0和使用Perl 5.8.8的Linux可以正常工作,因此它应该可以在最常见的Perl环境中移植。

As others have mentioned, select would not be a reliable choice as there may be times when you're reading from a process, but that process hasn't started writing yet.

正如其他人所提到的那样,select可能不是一个可靠的选择,因为有时您可能正在阅读一个流程,但该流程尚未开始编写。

All the best,

祝一切顺利,

Paul

#2


use POSIX 'isatty';
if ( ! @ARGV && isatty(*STDIN) ) {
    die "usage: ...";
}

See: http://www.opengroup.org/onlinepubs/009695399/functions/isatty.html

Note that select wouldn't be much help anyway, since it would produce false results if the piped info wasn't ready yet. Example:

请注意,select无论如何都不会有太大帮助,因为如果管道信息还没有准备就会产生错误的结果。例:

seq 100000|grep 99999|perl -we'$rin="";vec($rin,fileno(STDIN),1)=1;print 0+select($rin,"","",.01)'

#1


Perl comes with the -t file-test operator, which tells you if a particular filehandle is open to a TTY. So, you should be able to do this:

Perl附带-t file-test运算符,它告诉您特定的文件句柄是否对TTY开放。所以,你应该能够做到这一点:

if ( -t STDIN and not @ARGV ) {
    # We're talking to a terminal, but have no command line arguments.
    # Complain loudly.
}
else {
    # We're either reading from a file or pipe, or we have arguments in
    # @ARGV to process.
}

A quick test reveals this working fine on Windows with Perl 5.10.0, and Linux with Perl 5.8.8, so it should be portable across the most common Perl environments.

快速测试表明,在Windows上使用Perl 5.10.0和使用Perl 5.8.8的Linux可以正常工作,因此它应该可以在最常见的Perl环境中移植。

As others have mentioned, select would not be a reliable choice as there may be times when you're reading from a process, but that process hasn't started writing yet.

正如其他人所提到的那样,select可能不是一个可靠的选择,因为有时您可能正在阅读一个流程,但该流程尚未开始编写。

All the best,

祝一切顺利,

Paul

#2


use POSIX 'isatty';
if ( ! @ARGV && isatty(*STDIN) ) {
    die "usage: ...";
}

See: http://www.opengroup.org/onlinepubs/009695399/functions/isatty.html

Note that select wouldn't be much help anyway, since it would produce false results if the piped info wasn't ready yet. Example:

请注意,select无论如何都不会有太大帮助,因为如果管道信息还没有准备就会产生错误的结果。例:

seq 100000|grep 99999|perl -we'$rin="";vec($rin,fileno(STDIN),1)=1;print 0+select($rin,"","",.01)'