更新命令行输出

时间:2011-02-15 20:41:16

标签: perl backspace output-formatting

我的程序(碰巧在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中添加换行符,则不会打印退格符。但是,如果我省略换行符,则不会刷新输出缓冲区,也不会打印任何内容。

对此有什么好的解决方案?

5 个答案:

答案 0 :(得分:11)

对STDOUT使用autoflush:

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 :(得分:3)

$| = 1

在程序的早期某个地方为输出缓冲区打开autoflushing。

还可以考虑使用“\ r”将光标移回到行的开头,而不是尝试显式计算需要移回的空格数。

就像你说的那样,不要在进度计数器运行时打印换行符,否则你将在单独的行上打印出你的进度而不是覆盖旧行。

答案 2 :(得分:3)

我知道这不是你要求的,但可能更好。我碰巧遇到了同样的问题,所以不要过多地使用它Term::ProgressBar,看起来也不错。

答案 3 :(得分:1)

您也可以使用ANSI escape codes直接控制光标。或者您可以使用Term::ReadKey执行相同的操作。

答案 4 :(得分:0)

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

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

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