darkomen has asked for the wisdom of the Perl Monks concerning the following question:

I want to write some perl code that can detirmine when it has something in STDIN to process.

Ex: echo a | test.pl

That should process STDIN...

Ex: ./test.pl

That should exit without wanting a character entered into STDIN. Whenever you try and read from STDIN, if it is empty, it waits til it has something in it and gets an EOF... I want to basically be able to test.... Is there something in STDIN? Yes - process the contents of STDIN... No - Skip processing STDIN and exit....

Am I being clear at all? Thanks for any advice...

Replies are listed 'Best First'.
Re: Testing for the existence of STDIN?
by wog (Curate) on Jan 24, 2002 at 03:22 UTC
    In addition to the code above, you could use the -t filetest operator to check if STDIN was opened to a terminal (and thus not a pipe, etc):

    if (-t STDIN) { # we're running from a shell, without input being # piped to us. } else { # ... }
    Or you could also try a non-blocking read of STDIN, which most directly answers your original question of seeing if there is any input waiting without blocking:
    use IO::Handle; STDIN->blocking(0); # and try to read from it, like you would normally. my $line = <STDIN>; if (defined $line) { # we have input, read succeeded } else { # no input at the moment. }
    (Note that this technique may give false negatives if pipes take some time to start writing data.)

Re: Testing for the existence of STDIN?
by Zaxo (Archbishop) on Jan 24, 2002 at 03:28 UTC

    Four argument select 1, undef, undef, $timeout is what you're after.

    After Compline,
    Zaxo

(jeffa) Re: Testing for the existence of STDIN?
by jeffa (Bishop) on Jan 24, 2002 at 02:58 UTC
    This is expected behaviour. If you ask for something, Perl waits until it gets it. Your alternative is to pass arguments to the script, like the name of a file to open. If the file is empty, then you could exit cleanly.

    UPDATE:
    Actually, you _could_ use a time out with $SIG{ALRM}:

    $SIG{ALRM} = sub { die 'STDIN' }; eval { alarm(1); print while <>; alarm(0); }; print "no STDIN\n" if $@ =~ /STDIN/;
    You cannot get finer grained than one second with this way, but you can with select.

    Or .... just use wog's much more elegant solution. wog++

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      I have a piece of working code using sigalrm, i was just hoping there was more of a clean way to do so... It would be nice if you could use the -s test operator on STDIN...