Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Perl, how do I determine if there's a standard input present?

Tags:

stdin

perl

I've got a script that grabs standard input:

&process_input

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

When I run the script:

myscript.pl -param1=a -param2=b

I get stuck in this subroutine. Everything runs OK if I do:

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

How do I determine if I even have a standard input?

I would have thought that while(<STDIN>) would return false and not run, but I'm guessing it's actually waiting for you to type something in that why it's 'stuck'.

like image 288
EDJ Avatar asked Jun 04 '10 18:06

EDJ


3 Answers

You want to check where your STDIN (STanDard INput) is coming from: another application or a terminal. In your case, it's the second option, causing a read operation to stall the process until the user inputs something. For a solution, see 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
}

There's also IO::Interactive that might do better/more reliable checking.

like image 183
MvanGeest Avatar answered Oct 22 '22 15:10

MvanGeest


The statement <STDIN> does not return until you press Enter on the console. If you want to get around this, I believe that you can use IO::Handle to wrap STDIN, and call $stdin->blocking(0) to enable non-blocking I/O.

like image 2
JSBձոգչ Avatar answered Oct 22 '22 14:10

JSBձոգչ


That's normal. Standard usage for Unix tools is to use STDIN if no input file is given as an argument. Try cat, less, grep, etc. It's up to the caller to provide input, if only

tool < /dev/null

I strongly advise against trying to determine if "input" is available as it will introduce problems no matter how you achieve this. Specifically, avoid -t since it's problematic to fake a terminal when needed. Instead, rely on a more conventional interface.

If you want to make it possible to pass no input to your tool, it's weird that you'd be using STDIN in the first place. One would normally use an optional argument.

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

Another option would be to request that the user tells you when there is no input.

tool --batch

In order to help you with the design problems of your interface, it would really help to know what your tool does.

like image 1
ikegami Avatar answered Oct 22 '22 16:10

ikegami