tags:

views:

416

answers:

3

Hi!

When I write

#!/usr/bin/perl -w
use strict;

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    <>;
}

after each "return" I get one line.

Why don't I get with the next script after each "return" one paragraph?

#!/usr/bin/perl -w
use strict;

local $/ = "";

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    <>;
}

__DATA__
line one
line two
line three
line four
line five

line six
line seven
line eigth
line nine

line ten
line eleven
line twelve
+1  A: 

I guess you're expecting this line

local $/ = "";

to change the behaviour of

<DATA>

to keep reading until the end of the data.

But in fact it takes something like this

{
    local $/;  # $/ becomes undef in this block
    ...
}

to enable slurp mode (and to contain that mode to the scope inside the {curlys}).

In effect it's saying "forget about thinking of newlines as the end-of-record marker",

Besides that... there's a tie fighter in your code!

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    <>;    # <-- Feel the power of the DARK SIDE!!!
}

This little guy will read from STDIN, not from DATA - is that really what you want?

Ed Guiness
Actually, the Perl "tie fighter" is the "<=>", which we also sometimes call the "spaceship operator".
brian d foy
I know, but <> is so close my smirking Friday brain couldn't resist leaping that little detail.
Ed Guiness
Methinks we're going to have to invent a `<-o->` operator.
Sinan Ünür
@edg: I think it's pretty clear that reading from STDIN is intentional, but that he wants paragraph mode on DATA only, not on STDIN.
ysth
+3  A: 

In your first script, with the $/ variable set to default "\n", the <DATA> will only return one line at a time.

I believe the second script does what you want, it's just that <> won't terminate the read on a 'return' but rather on a <ctrl-d> due to your $/ setting (as someone else pointed out <> reads from STDIN but I think you already know that and are using it to regulate the output).

If you really want to regulate the output with 'return' then you need to do more with $/ in the loop.

while( <DATA> ) {
    print "\n-------------------------\n\n";
    print;
    $/ = "\n"; # default so that the following terminates the read on 'return'
    <>;
    $/ = ""; 
}   
shank
I would use `{$/="\n";<>}`
Brad Gilbert
+1  A: 

Using <> that way (interactively) in paragraph mode is going to be confusing. It won't return when you hit "return"; instead, it will read until it gets a non empty line (the start of a paragraph), then read until it gets an empty line (the end of that paragraph), then continue reading until it gets a non-empty line (the start of the following paragraph - which will be buffered, not returned) so it knows that it's discarded any extra empty lines.

Perhaps you should be using:

local $/ = "\n"; <>

at the end of your loop instead. Or maybe POSIX::getchar().

ysth