【问题标题】:In Perl, how do I determine if there's a standard input present?在 Perl 中,如何确定是否存在标准输入?
【发布时间】:2010-06-04 18:02:29
【问题描述】:

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

&process_input

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

当我运行脚本时:

myscript.pl -param1=a -param2=b

我陷入了这个子程序。如果我这样做,一切运行正常:

echo "" | myscript.pl -param1=a -param2=b

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

我原以为 while(&lt;STDIN&gt;) 会返回 false 并且不会运行,但我猜它实际上是在等待您输入一些内容来说明它为什么会“卡住”。

【问题讨论】:

标签: perl stdin


【解决方案1】:

您想检查您的 STDIN(标准输入)来自哪里:另一个应用程序或终端。在您的情况下,这是第二个选项,导致读取操作暂停该过程,直到用户输入某些内容。如需解决方案,请参阅How can I tell if STDIN is connected to a terminal in Perl?

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

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

【讨论】:

  • 谢谢!由于脚本也可以由另一个应用程序运行,我可以使用 -t 选项。
【解决方案2】:

在您按控制台上的 Enter 之前,语句 &lt;STDIN&gt; 不会返回。如果你想解决这个问题,我相信你可以使用IO::Handle包装STDIN,并调用$stdin-&gt;blocking(0)启用非阻塞I/O。

【讨论】:

  • 问题不是阻塞 IO,而是&lt;FILEHANDLE&gt;(相当于readline(*FILEHANDLE))正在寻找一行输入。直到找到\n(从技术上讲,是输入记录分隔符$/ 的一个实例),它才会返回。手柄是否阻塞并不重要。另外,如果你使用IO::Handle,你可以简单地在现有的全局句柄上使用它的方法:STDIN-&gt;blocking(0);
【解决方案3】:

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

tool < /dev/null

我强烈建议不要尝试确定“输入”是否可用,因为无论您如何实现它都会带来问题。具体来说,避免使用-t,因为在需要时伪造终端是有问题的。相反,请依赖更传统的界面。

如果您希望不向您的工具传递任何输入,那么您一开始就使用 STDIN 是很奇怪的。通常会使用可选参数。

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

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

tool --batch

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

【讨论】:

    【解决方案4】:

    当用户键入 Ctrl + Dend-of-file 字符时,您的程序将继续。

    【讨论】:

      猜你喜欢
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      • 2019-11-15
      • 2012-02-10
      • 1970-01-01
      • 2020-11-23
      相关资源
      最近更新 更多