【问题标题】:How to show and update echo on same line如何在同一行显示和更新回声
【发布时间】:2012-09-27 18:58:49
【问题描述】:

我在 Bash 中有以下内容(在 Linux 中)

for dir in Movies/*
do
  (cd "$dir" && pwd|cut -d \/ -f5|tr -s '\n' ', ' >> ../../movielist &&
  exiftool * -t -s3 -ImageSize -FileType|tr -s '\t' ',' >> ../../movielist )
echo "Movie $movies - $dir ADDED!"
let movies=movies+1
done

但我希望这样“回声”在下一行显示以下回声(不与最后一个回声输出连接而是替换它),使其看起来像是在更新。类似于在同一行显示百分比的进度条。

【问题讨论】:

    标签: bash


    【解决方案1】:

    好吧,我没有正确阅读 man echo 页面。

    如果我添加第三个转义字符,echo 有 2 个选项可以做到这一点。

    这两个选项是-n-e

    -n 不会输出尾随的换行符。这样一来,我每次回显某些内容时就不用换行了。

    -e 将允许我解释反斜杠转义符号。

    猜猜我想用什么转义符号:\r。是的,回车会让我回到开头,看起来我在同一行进行更新。

    所以回声线看起来像这样:

    echo -ne "Movie $movies - $dir ADDED!"\\r

    我不得不逃脱转义符号,这样 Bash 就不会杀死它。这就是为什么您会在其中看到 2 个\ 符号。

    正如威廉所说,printf 也可以执行类似(甚至更广泛)的任务。

    【讨论】:

    • 只是对未来的说明:printf 将做完全相同的事情,没有任何选项。优点是 printf 通常在每个环境和操作系统中的行为都相似,而 echo 有时会表现得非常不同。对于跨平台脚本(或者如果您认为您可能会关心它),使用 printf 是最佳实践。
    • printf a; printf b 输出ab --- printf a\\r; printf b 输出b --- printf a\\r; sleep 1; printf b 输出a,然后是b
    【解决方案2】:

    如果我理解得很好,您可以用以下行替换您的回声:

    echo -ne "Movie $movies - $dir ADDED! \033[0K\r"
    

    这是一个小例子,您可以运行它来了解它的行为:

    #!/bin/bash
    for pc in $(seq 1 100); do
        echo -ne "$pc%\033[0K\r"
        sleep 1
    done
    echo
    

    【讨论】:

    • 似乎在 zsh 上 K 不是必需的,实际上是作为字母 K 输出的。
    • 很好的例子 - 对我来说,一开始的哈希爆炸是关键
    【解决方案3】:

    其余的答案都很好,但只是想添加一些额外的信息,以防有人来这里寻找替换/更新多行回显的解决方案。

    所以我想和大家分享一个例子。下面的脚本是在 CentOS 系统上尝试的,它使用“timedatectl”命令,它基本上打印了你系统的一些详细时间信息。

    我决定使用该命令,因为它的输出包含多行并且非常适合以下示例:

    #!/bin/bash
    while true; do
      COMMAND=$(timedatectl) #Save command result in a var.
      echo "$COMMAND" #Print command result, including new lines.
    
      sleep 3 #Keep above's output on screen during 3 seconds before clearing it
    
      #Following code clears previously printed lines
      LINES=$(echo "$COMMAND" | wc -l) #Calculate number of lines for the output previously printed
      for (( i=1; i <= $(($LINES)); i++ ));do #For each line printed as a result of "timedatectl"
        tput cuu1 #Move cursor up by one line
        tput el #Clear the line
      done
    
    done
    

    上面将永远打印“timedatectl”的结果,并将用更新的结果替换之前的回显。

    我必须提到,这段代码只是一个示例,但根据您的需要,可能不是最适合您的解决方案。 一个类似的命令几乎相同(至少在视觉上)是“watch -n 3 timedatectl”。

    但那是另一回事。 :)

    希望有帮助!

    【讨论】:

      【解决方案4】:

      我使用 printf,它更短,因为它不需要标志来完成工作:

      printf "\rMy static $myvars composed text"
      

      【讨论】:

      • 我试图从我的 shell 配置中实现这一点,该配置正在采购深度嵌套的脚本(a 调用 b 调用 z....)最终被调用的脚本无法给我一个可预测的echo -ne 的行为。感谢printf前来救援。此外,我相信printf 具有跨平台的一致行为。对于可再分配的工作非常有价值!感谢OP的回答!
      • 不客气,感谢您的支持。我们努力为人民服务。
      【解决方案5】:

      这很有用,请尝试并根据需要进行更改。

      #!/bin/bash
      for load in $(seq 1 100); do
          echo -ne "$load % downloded ...\r"
          sleep 1
      done
      echo "100"
      echo "Loaded ..."
      

      【讨论】:

        【解决方案6】:

        你可以试试这个..我自己的版本..

        funcc() {
        while true ; do 
        for i in \| \/ \- \\ \| \/ \- \\; do 
          echo -n -e "\r$1  $i  "
        sleep 0.5
        done  
        #echo -e "\r                                                                                      "
        [ -f /tmp/print-stat ] && break 2
        done
        }
        
        funcc "Checking Kubectl" & &>/dev/null
        sleep 5
        touch /tmp/print-stat
        echo -e "\rPrint Success                  "
        

        【讨论】:

          【解决方案7】:

          我最喜欢的方法是休眠到 50。这里需要在 echo 语句中使用 i 变量。

          for i in $(seq 1 50); do
            echo -ne "$i%\033[0K\r"
            sleep 50
          done
          echo "ended"
          

          【讨论】:

          • 这很好,但是光标遮住了第一个字符。我想 echo 中的一些空格可以解决这个问题。
          • 我试图从我的 shell 配置中实现这一点,该配置正在采购深度嵌套的脚本(a 调用 b 调用 z....)最终被调用的脚本无法给我一个可预测的echo -ne 的行为。感谢printf前来救援。此外,我相信printf 具有跨平台的一致行为。对于可再分配的工作非常有价值!感谢OP的回答。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-03-23
          • 2015-10-17
          • 2015-09-12
          • 1970-01-01
          • 2019-07-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多