Вопрос

Моя программа (которая, оказывается, написана на Perl, хотя я не думаю, что этот вопрос специфичен для Perl) выводит сообщения о состоянии в какой-то момент в программе вида Progress: x/yy где x и yy являются числом, как: Progress: 4/38.

Я бы хотел "перезаписать" предыдущий вывод при печати нового сообщения о состоянии, чтобы я не заполнял экран сообщениями о состоянии.До сих пор я пробовал это:

my $progressString = "Progress\t$counter / " . $total . "\n";
print $progressString;
#do lots of processing, update $counter
my $i = 0;
while ($i < length($progressString)) {
    print "\b";
    ++$i;
}

Символ обратного пробела не будет печататься, если я добавлю новую строку в $progressString.Однако, если я опущу новую строку, выходной буфер никогда не будет очищен, и ничего не будет напечатано.

Какое хорошее решение для этого есть?

Это было полезно?

Решение

Используйте автозапись со Stdout:

local $| = 1; # Or use IO::Handle; STDOUT->autoflush;

print 'Progress: ';
my $progressString;
while ...
{
  # remove prev progress
  print "\b" x length($progressString) if defined $progressString;
  # do lots of processing, update $counter
  $progressString = "$counter / $total"; # No more newline
  print $progressString; # Will print, because auto-flush is on
  # end of processing
}
print "\n"; # Don't forget the trailing newline
.

Другие советы

сказать

$| = 1
.

где-то рано в вашей программе, чтобы включить автозагрузку на выходной буфер.

Также рассмотрите возможность использования «\ R», чтобы переместить курсор обратно в начало строки, а не пытаться явно подсчитать, сколько пробелов нужно вернуть обратно.

Как вы сказали, не раскладывайте новую строку, пока ваш счетчик прогресса работает или вы распечатаете свой прогресс на отдельной строке, а не перезаписываете старую строку.

Я знаю, это не совсем то, о чем вы просили, но, возможно, лучше.Я столкнулся с такой же проблемой, и поэтому вместо того, чтобы слишком много разбираться с ней, перешел к использованию Term::ProgressBar что тоже выглядит неплохо.

Вы также можете использовать ensi escape isseps для непосредственного управления курсоромОтказИли вы можете использовать Срок :: readkey для того, чтобы сделать то же самое.

Мне пришлось решать что-то похожее на это сегодня. Если вы не возражаете против перепечатки всей строки, вы можете сделать что-то подобное:

print "\n";
while (...) {
     print "\rProgress: $counter / $total";
     # do processing work here
     $counter++;
}
print "\n";
.

Персонаж «\ R» - это возвращение каретки - она приносит курсор обратно в начало строки.Таким образом, все, что вы распечатаете, перезаписывают предыдущий текст уведомления о прогрессе.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top