我的程序(碰巧是用 Perl 编写的,尽管我不认为这个问题是 Perl 特定的)在程序中的某一点输出状态消息: Progress: x/yy 在哪里 xyy 是一个数字,例如: 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 看起来也不错。

您还可以使用 ANSI 转义码 直接控制光标。或者你可以使用 术语::读取密钥 做同样的事情。

我今天必须解决类似的问题。如果您不介意重新打印整行,您可以这样做:

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

“ ”字符是一个回车符——它将光标带回行首。这样,您打印出的任何内容都会覆盖先前进度通知的文本。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top