开发者

Why does adding or removing a newline change the way this perl for loop functions?

开发者 https://www.devze.com 2023-01-10 17:41 出处:网络
I\'m starting to learn perl, using the Wrox Beginning Perl available on perl.org and have a question regarding a for loop example they provide in Chapter 3.

I'm starting to learn perl, using the Wrox Beginning Perl available on perl.org and have a question regarding a for loop example they provide in Chapter 3.

#!/usr/bin/perl

use warnings;
use strict;

my @count = (1..10);
for (reverse(@count)) {
        print "$_...\n";
        sleep 1;
}
print "Blast Off!\n"

This is the script they provide, and it works as expected. It displays a number followed by ... every second, waiting a second in between each number. When done, it displays Blast Off!

However if I remove the newline from the print statement, the behaviour changes. The script silently waits 10 seconds and then displays all 10 numbers and Blash Off! at once. Why the change?

#!/usr/bin/perl

use warnings;
use strict;

my @count = (1.开发者_JAVA百科.10);
for (reverse(@count)) {
        print "$_...";
        sleep 1;
}
print "Blast Off!\n"


Perl is buffering the print output and the buffer isn't flushed until the newline. Alternatively, you can add $| = 1 before your loop to tell Perl to flush the buffer between the print statements, thus giving you the expected output with the proper delay:

#!/usr/bin/perl

use warnings;
use strict;

$| = 1; #Add this line
my @count = (1..10);
for (reverse(@count)) {
        print "$_...";
        sleep 1;
}
print "Blast Off!\n"'


You are looking at the standard behavior of the line-oriented output of the C stdio library when writing to a terminal.

See autoflush for perl details.


Standard output is line buffered. It won't flush the buffer until it sees a newline. You can correct this by adding the following line before the loop:

my $ofh = select(STDOUT); $| = 1; select $ofh;

Let's break that down:

my $ofh = select(STDOUT); - selects the STDOUT (standard output) as the current selected file handle, and stores whatever was the previous selected file handle in $ofh

$| = 1; - sets the current file handle (ie. STDOUT) to unbuffered.

select $ofh; - reselects whatever was the selected file handle before, so that if the code had selected a file handle other than STDOUT at some point, it will still be selected after this line of code is finished.


A neater way than using select() to set the autoflush flag on STDOUT is to use IO::Handle (which has been included with the Perl core since version 5.004):

use IO::Handle;
STDOUT->autoflush(1)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号