题
我的程序(碰巧是用 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
在程序早期的某个位置打开输出缓冲区的自动刷新。
还可以考虑使用“ ”将光标移回行首,而不是尝试显式计算需要移回多少个空格。
就像你说的,在进度计数器运行时不要打印换行符,否则你将在单独的行上打印进度而不是覆盖旧行。
我知道这不完全是你所要求的,但可能更好。我遇到了同样的问题,所以与其过多地处理它,不如使用 Term::ProgressBar
看起来也不错。
我今天必须解决类似的问题。如果您不介意重新打印整行,您可以这样做:
print "\n";
while (...) {
print "\rProgress: $counter / $total";
# do processing work here
$counter++;
}
print "\n";
“ ”字符是一个回车符——它将光标带回行首。这样,您打印出的任何内容都会覆盖先前进度通知的文本。
不隶属于 StackOverflow