命令行工具输出后如何更改输出?

The*_*ist 12 c++ terminal command-line haskell node.js

我注意到很多命令行工具,例如wget,会将进度显示为一个数字或进度条,它在进程完成时前进.虽然问题不是特定于语言,但我最常用于命令行工具(C++,Node.js,Haskell)的语言中,我还没有看到过这样做的方法.

这是一个示例,当wget下载文件时,单行终端的三个快照:开始过程过程中过程接近完成

除了其他信息外,wget还会显示一个进度条(<=>),它会在下载文件时前进.到目前为止下载的数据量(6363,179561,316053)和当前下载速度(10.7KB/s,65.8KB/s,63.0KB/s)也会更新.这是怎么做到的?

理想情况下,请包含上述三种语言中的一种或多种语言的代码示例.

Eri*_*ikR 12

只需打印CR(不带换行符)即可覆盖一行.这是perl中的示例程序:

#!/usr/bin/env perl

$| = 1;

for (1..10) {
  print "the count is: $_\r";
  sleep(1)
}
Run Code Online (Sandbox Code Playgroud)

我还禁用了输出缓冲($| = 1),以便print命令立即将其输出发送到控制台而不是缓冲它.

Haskell示例:

import System.IO
import Control.Monad
import Control.Concurrent

main = do
  hSetBuffering stdout NoBuffering
  forM_ [1..10] $ \i -> do
    putStr $ "the count is: " ++ show i ++ "\r"
    threadDelay 1000000
Run Code Online (Sandbox Code Playgroud)


aa3*_*333 5

在GitHub上查看GNU wget repo - progress.c

它们似乎以相同的方式执行,即打印\r然后覆盖.

/* Print the contents of the buffer as a one-line ASCII "image" so
   that it can be overwritten next time.  */

static void
display_image (char *buf)
{
  bool old = log_set_save_context (false);
  logputs (LOG_VERBOSE, "\r");
  logputs (LOG_VERBOSE, buf);
  log_set_save_context (old);
}
Run Code Online (Sandbox Code Playgroud)