【问题标题】:How to print out to the same line, overriding previous line?如何打印到同一行,覆盖前一行?
【发布时间】:2013-08-02 12:47:24
【问题描述】:

有时我会在终端中看到一些将结果打印到标准输出但在同一行的命令。例如 wget 打印如下箭头:

0[=>        ]100%
0[  =>      ]100%
0[    =>    ]100%
0[      =>  ]100%
0[        =>]100%

但它被打印到同一行,所以看起来箭头在移动。如何使用 bash 或 sh 在我的程序中实现相同的目标?我需要使用其他工具吗?

更新:

我知道我提到了 wget,它默认出现在 linux 中,基于 GNU 的 unices ......是否也有适用于 BSD 的通用方法? (如 OSX)-> 好的,如果我使用 bash 而不是 sh,那么它可以工作:)

【问题讨论】:

标签: bash shell


【解决方案1】:

使用特殊字符\r。它返回到行首而不转到下一行。

for i in {1..10} ; do
    echo -n '['
    for ((j=0; j<i; j++)) ; do echo -n ' '; done
    echo -n '=>'
    for ((j=i; j<10; j++)) ; do echo -n ' '; done
    echo -n "] $i"0% $'\r'
    sleep 1
done

【讨论】:

  • 很好的答案,@choroba。这样就完成了:for i in {1..10} ; do echo -n "0[ "; for ((j=0; j&lt;i; j++)) ; do echo -n ' '; done; echo -n '=&gt;' ; for ((j=i;j&lt;=10;j++)) ; do echo -n ' '; done; echo -n $'] 100% \r'; sleep 1; done
【解决方案2】:

您可以为此使用\r

例如,这将在同一行中不断更新当前时间:

while true; do echo -ne "$(date)\r"; done

【讨论】:

  • 另请注意,它不适用于 POSIX echo 命令,但在 bash 中运行良好
  • 是的,出于可移植性原因,printf 应优先于带有选项参数的echo
【解决方案3】:

您也可以使用ANSI/VT100 terminal escape sequences 来实现此目的。

这是一个简短的例子。当然,您可以将printf 语句合并为一个。

#!/bin/bash

MAX=60
ARR=( $(eval echo {1..${MAX}}) )

for i in ${ARR[*]} ; do 
    # delete from the current position to the start of the line
    printf "\e[2K"
    # print '[' and place '=>' at the $i'th column
    printf "[\e[%uC=>" ${i}
    # place trailing ']' at the ($MAX+1-$i)'th column
    printf "\e[%uC]" $((${MAX}+1-${i}))
    # print trailing '100%' and move the cursor one row up
    printf " 100%% \e[1A\n"

    sleep 0.1
done

printf "\n"

使用转义序列,您可以最大程度地控制终端屏幕。

您可以在 [1] 上找到可能序列的概述。

[1]http://ascii-table.com/ansi-escape-sequences-vt-100.php

【讨论】:

    猜你喜欢
    • 2014-12-22
    • 1970-01-01
    • 2021-10-24
    • 2017-04-07
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多