更新命令行输出
Posted
技术标签:
【中文标题】更新命令行输出【英文标题】:Update command line output 【发布时间】:2011-06-27 21:53:44 【问题描述】:我的程序(恰好在 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
中包含换行符,则不会打印退格字符。但是,如果我省略换行符,则输出缓冲区永远不会被刷新,也不会打印任何内容。
有什么好的解决方案?
【问题讨论】:
【参考方案1】:您也可以使用ANSI escape codes 直接控制光标。或者你可以使用Term::ReadKey 来做同样的事情。
【讨论】:
【参考方案2】:我知道这并不完全符合您的要求,但可能更好。我也遇到了同样的问题,所以与其处理太多,不如使用Term::ProgressBar
,这看起来也不错。
【讨论】:
【参考方案3】:我今天不得不处理类似的事情。 如果您不介意重新打印整行,您可以执行以下操作:
print "\n";
while (...)
print "\rProgress: $counter / $total";
# do processing work here
$counter++;
print "\n";
“\r”字符是一个回车符——它将光标带回到行首。这样,您打印的任何内容都会覆盖之前的进度通知文本。
【讨论】:
【参考方案4】:对 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
【讨论】:
这类作品。我最终得到了相当乱码的输出,例如:5 / 73 / 70 / 7
。在代码运行时,我看到“进度”一词和数字的各种乱码形式。
我认为处理代码中的某些内容与标准输出有关。就其本身而言,您的代码有效。谢谢!【参考方案5】:
说
$| = 1
在程序早期的某个地方为输出缓冲区打开自动刷新。
还可以考虑使用“\r”将光标移回行首,而不是尝试明确计算需要移回多少空格。
如您所说,在进度计数器运行时不要打印换行符,否则您将在单独的行上打印进度而不是覆盖旧行。
【讨论】:
以上是关于更新命令行输出的主要内容,如果未能解决你的问题,请参考以下文章