在Perl中,如何确定是否存在标准输入?

6
我有一个抓取标准输入的脚本:
&process_input

sub process_input {
    while(<STDIN>) {
       $log_data .= $_;
    }
}

当我运行这个脚本时:

myscript.pl -param1=a -param2=b

我卡在这个子程序里了。如果我执行以下操作,一切正常:
echo "" | myscript.pl -param1=a -param2=b

如何确定我是否拥有标准输入?

我本以为while(<STDIN>)会返回false并停止运行,但我猜它实际上在等待你输入一些内容,这就是为什么它“卡住”的原因。


1
可能是如何在Perl中判断STDIN是否连接到终端?的重复问题。 - Ether
4个回答

20

您想检查STDIN(标准输入)来自哪里:另一个应用程序还是终端。在您的情况下,它是第二个选项,导致读取操作使进程停滞,直到用户输入。有关解决方案,请参见如何在Perl中判断STDIN是否连接到终端?

if (-t STDIN) {
    # input attached to terminal and will probably ask user
} else {
    # input from other process
}

还有IO::Interactive,它可能会进行更好/更可靠的检查。


谢谢!由于脚本也可以被另一个应用程序运行,我可以使用“-t”选项。 - EDJ

2

语句<STDIN>在控制台上按下Enter之前不会返回。如果你想绕过这个问题,我相信可以使用IO::Handle来包装STDIN,并调用$stdin->blocking(0)以启用非阻塞I/O。


2
问题不在于阻塞IO,而是<FILEHANDLE>(相当于readline(*FILEHANDLE))正在寻找一行输入。它将一直等待,直到找到\n(技术上来说是输入记录分隔符$/的一个实例)。无论句柄是否阻塞都没有关系。此外,如果您使用IO::Handle,您可以简单地在现有的全局句柄上使用其方法:STDIN->blocking(0); - daotoad

1

这是正常的。Unix 工具的标准用法是如果没有输入文件作为参数,则使用 STDIN。尝试使用 catlessgrep 等命令。如果只有输入,那么由调用者提供。

tool < /dev/null

我强烈建议不要尝试确定是否有"input"可用,因为无论你如何实现都会引入问题。特别是避免使用 -t,因为在需要时伪造终端是有问题的。相反,应该依赖于更传统的接口。

如果您想要使得传递没有输入给您的工具成为可能,那么首先使用 STDIN 是很奇怪的。通常会使用一个可选参数。

tool --foo file
tool --foo <( echo "" )

另一个选择是要求用户在没有输入时告诉您。

tool --batch

为了帮助您解决界面设计问题,了解您的工具功能将非常有帮助。

0

当用户键入 Ctrl + D,即 end-of-file 字符时,您的程序将继续运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接