Обновить вывод командной строки
-
14-11-2019 - |
Вопрос
Моя программа (которая, оказывается, написана на 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» - это возвращение каретки - она приносит курсор обратно в начало строки.Таким образом, все, что вы распечатаете, перезаписывают предыдущий текст уведомления о прогрессе.