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

一世执手 提交于 2019-12-23 19:24:04

问题


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..10);
for (reverse(@count)) {
        print "$_...";
        sleep 1;
}
print "Blast Off!\n"

回答1:


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"'



回答2:


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.




回答3:


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.




回答4:


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)


来源:https://stackoverflow.com/questions/3445468/why-does-adding-or-removing-a-newline-change-the-way-this-perl-for-loop-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!