更新命令行输出

Posted

技术标签:

【中文标题】更新命令行输出【英文标题】:Update command line output 【发布时间】:2011-06-27 21:53:44 【问题描述】:

我的程序(恰好在 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 中包含换行符,则不会打印退格字符。但是,如果我省略换行符,则输出缓冲区永远不会被刷新,也不会打印任何内容。

有什么好的解决方案?

【问题讨论】:

【参考方案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”将光标移回行首,而不是尝试明确计算需要移回多少空格。

如您所说,在进度计数器运行时不要打印换行符,否则您将在单独的行上打印进度而不是覆盖旧行。

【讨论】:

以上是关于更新命令行输出的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 CMake 获取命令行输出作为参数?

Xcode 4.5命令行单元测试

cmd命令行中logcat输出日志中文乱码

JAVA日志信息在命令行输出带颜色的字符串是怎么实现的

项目实战:Qt终端命令模拟工具 v1.0.0(实时获取命令行输出,执行指令,模拟ctrl+c中止操作)

项目实战:Qt终端命令模拟工具 v1.0.0(实时获取命令行输出,执行指令,模拟ctrl+c中止操作)