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

Say I want to read multi-line user input, do something with it, then read some more. I try,
#!/usr/bin/perl use strict; my $input; local $/; $input = <STDIN>; print $input; $input = <STDIN>; print $input;
It receives user input the first time, but prints and exits the script without letting me receive user input the second time. I tried undefining $/ in a separate block, and just seeing if I could read single line input the second time, but it does the same thing - just does the first read, then exits:
#!/usr/bin/perl use strict; my $input; { local $/; $input = <STDIN>; } print $input; $input = <STDIN>; print $input;
this doesn't work either:
#!/usr/bin/perl use strict; my $holdRS = $/; local $/; my $input = <STDIN>; $/ = $holdRS; print $input; my $holdRS = $/; local $/; my $input2 = <STDIN>; $/ = $holdRS; print $input2;
This works though:
#!/usr/bin/perl use strict; my @userinput = <STDIN>; foreach (@userinput) { print; } my @userinput = <STDIN>; foreach (@userinput) { print; }
What is it about undefining $/ that allows me to read user input only one time? (even if I set it back to default first)

Replies are listed 'Best First'.
Re: how to read STDIN interactively
by ikegami (Patriarch) on Feb 24, 2011 at 15:54 UTC
    If it's undef, you're saying there's no line terminator, so it reads until the end of the file.
      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.

        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
        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.
        ...excuse me, 2nd to the last example
Re: how to read STDIN interactively
by Corion (Patriarch) on Feb 24, 2011 at 15:55 UTC

    Once you set $/ to undef, <...> will keep reading until the filehandle is exhausted. After that, you will likely need to reopen STDIN to start reading from it again.

      No, not if STDIN is a terminal. Terminals automatically re-open, in effect. That's what you can rely on read functions to return EOF more than once, and why you sometimes have to signal EOF more than once to exit some applications.
Re: how to read STDIN interactively
by DrHyde (Prior) on Feb 25, 2011 at 10:29 UTC
    Why doesn't what work? You're far more likely to get useful responses if you use a descriptive title, so that people can see what you're talking about from the index on the "newest nodes" page etc.