Why does adding or removing a newline change the way this perl for loop functions?
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)
精彩评论