in reply to Re^2: how to read STDIN interactively
in thread how to read STDIN interactively

I don't understand,

My fault. I misunderstood the problem. Basically, I made the same mistake you did.

Starting fresh:

If you wanted to read to EOF, you'd write

while (<STDIN>) { print; }

You want to read to EOF twice, so you'd write

for (1..2) { while (<STDIN>) { print; } }

You don't want to read a line at a time, so

local $/; for (1..2) { while (<STDIN>) { print; } }

Now count the number of times <STDIN> executed: 4.

local $/; $_ = <STDIN>; # Returns first chunk print; $_ = <STDIN>; # Returns EOF $_ = <STDIN>; # Returns second chunk print; $_ = <STDIN>; # Returns EOF

In all but the last snippet, you are calling readline (<>) in scalar context. It returns undef on eof (and on error).

readline (like glob and each) needs to signal when it has finished return results when used as an iterator. You're forgetting to absorb this signal.

The simplest solution is to call readline in list context.

local $/; ($_) = <STDIN>; # Returns first chunk ($_) = <STDIN>; # Returns second chunk

Replies are listed 'Best First'.
Re^4: how to read STDIN interactively
by Allasso (Monk) on Feb 25, 2011 at 01:14 UTC
    Okay, yes, I can see that's what it is doing - the second time it returns EOF.

    But I don't understand why then, if I am reading a line at a time, ($/ = \n) I don't have to read twice - once to read the chunk, and once to read the newline.

    Also, why doesn't it work in the case when I made $/ local and undefined it in its own namespace, and the other case where I set $/ back to a newline immediately after the read.

    I agree, reading it in list context is the simplest way, but I'd like to understand what is going on.

      The undef being returned isn't the value of $/, it's a signal that EOF was reached.

      Your are mistaken about the behaviour being different when $/ eq "\n". It doesn't matter what $/ is. If you only have one line, the second read will be undef.

      $ echo "abc" | perl -E'$/ = undef; say defined(<>)||0 for 1..2;' 1 0 $ echo "abc" | perl -E'$/ = "\n"; say defined(<>)||0 for 1..2;' 1 0

      You saw a difference in your tests because you passed two lines before EOF with $/ eq "\n", but only one line before EOF with !defined($/).

      By the way, relying on the user to close STDIN between inputs creates a stinky interface.

        It looks like I am lacking some needed basic prerequisite stuff to understand what you all are talking about. I'm gonna need to do some studying.

        thanks much.