Почему добавление или удаление новой строки изменяет способ, которым этот perl для функций цикла? - PullRequest
3 голосов
/ 10 августа 2010

Я начинаю изучать Perl, используя Perl Wrox Beginning, доступный на perl.org , и у меня возник вопрос относительно примера цикла for, который они приводят в главе 3.

#!/usr/bin/perl

use warnings;
use strict;

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

Это скрипт, который они предоставляют, и он работает как положено.Он отображает число, за которым следует ... каждую секунду, ожидая секунду между каждым номером.Когда это будет сделано, отобразится Blast Off!

Однако, если я удалю символ новой строки из оператора печати, поведение изменится.Сценарий молча ждет 10 секунд, а затем отображает все 10 чисел и Blash Off! одновременно.Почему изменения?

#!/usr/bin/perl

use warnings;
use strict;

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

Ответы [ 4 ]

11 голосов
/ 10 августа 2010

Perl буферизирует вывод print, и буфер не очищается до новой строки. В качестве альтернативы, вы можете добавить $| = 1 перед циклом, чтобы указать Perl очистить буфер между операторами печати, что даст вам ожидаемый результат с соответствующей задержкой:

#!/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"'
4 голосов
/ 10 августа 2010

Вы смотрите на стандартное поведение строчно-ориентированного вывода библиотеки C stdio при записи в терминал.

Подробнее о perl см. autoflush .

4 голосов
/ 10 августа 2010

Стандартный вывод буферизован.Он не очистит буфер, пока не увидит новую строку.Вы можете исправить это, добавив следующую строку перед циклом:

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

Давайте разберем это:

my $ofh = select(STDOUT); - выбирает STDOUT (стандартный вывод) в качестве текущего дескриптора выбранного файлаи сохраняет все, что было ранее выбранным дескриптором файла в $ofh

$| = 1; - устанавливает текущий дескриптор файла (т. е. STDOUT) в небуферизованный.ранее выбранный дескриптор файла, поэтому, если код выбрал в какой-то момент другой дескриптор файла, отличный от STDOUT, он все равно будет выбран после завершения этой строки кода.

1 голос
/ 10 августа 2010

Более простой способ, чем использовать select () для установки флага автоматической очистки на STDOUT, - это использовать IO :: Handle (который был включен в ядро ​​Perl с версии 5.004):

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