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

I don't understand, I thought I was sending it EOF when I hit ^D at the end of my input. That's how I get it to print the first time.

Also, in the last example, I am returning $/ to a newline.

Replies are listed 'Best First'.
Re^3: how to read STDIN interactively
by ikegami (Patriarch) on Feb 24, 2011 at 21:39 UTC

    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
      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.

Re^3: how to read STDIN interactively
by DrHyde (Prior) on Feb 25, 2011 at 10:48 UTC
    By the time you reset $/ the script has already read STDIN all the way to the end of the "file", so the second <STDIN> has nothing left to read.
Re^3: how to read STDIN interactively
by Allasso (Monk) on Feb 24, 2011 at 21:03 UTC
    ...excuse me, 2nd to the last example