在 Bash 中覆盖先前的输出而不是附加它

NES*_*NES 24 command-line bash scripts

对于 bash 计时器,我使用以下代码:

#!/bin/bash
sek=60
echo "60 Seconds Wait!"
echo -n "One Moment please "
while [ $sek -ge 1 ]
do
   echo -n "$sek "  
sleep 1
   sek=$[$sek-1]
done
echo
echo "ready!"
Run Code Online (Sandbox Code Playgroud)

这给了我类似的东西

One Moment please: 60 59 58 57 56 55 ...
Run Code Online (Sandbox Code Playgroud)

是否有可能用最新的值替换 second 的最后一个值,以便输出不会产生大的轨迹,而是像一个位置的实时秒数一样倒计时?(希望你明白我的意思:))

Mik*_*kel 18

基本上与 aneeshep 的答案相同,但使用 Return ( \r) 而不是 Backspace ( \b) 因为我们不知道长度是否总是相同的,例如 when $sek < 10

此外,您的第一个echo应该使用$sek,而不是硬编码60

最后,注意....后面的空格。

#!/bin/bash
sek=60
echo "$sek Seconds Wait!"
while [ $sek -ge 1 ]
do
   echo -ne "One Moment please $sek ... \r"
   sleep 1
   sek=$[$sek-1]
done
echo
echo "ready!"
Run Code Online (Sandbox Code Playgroud)


ane*_*hep 15

#!/bin/bash
sek=60
echo "60 Seconds Wait!"
echo -n "One Moment please "
while [ $sek -ge 1 ]
do
   echo -n "$sek" #print sek
   sleep 1
   sek=$[$sek-1] #update sek
   echo -en "\b\b\b" #'print' backtrace
done
echo
echo "ready!"
Run Code Online (Sandbox Code Playgroud)

  • 来自 bash 的手册:`旧格式 $[expression] 已弃用,将在即将推出的 bash 版本中删除。`。使用POSIX `$((表达式))` 或`((`-command 代替。例如`sek=$(( sek - 1 ))` 或`(( sek = sek - 1 ))` 或`(( sek--))`。 (3认同)
  • 太棒了,非常感谢。只是给其他读者的一个通知。为了适应上面的代码,你必须使用 echo -en "\b\b\b" 因为空间。 (2认同)

gei*_*rha 7

使用 bash,您可以使用特殊变量SECONDS

#BASH
SECONDS=0;
while sleep .5 && ((SECONDS <= 60)); do 
    printf '\r%s: %2d' "One moment please" "$((60-SECONDS))"
done
printf '\n'
Run Code Online (Sandbox Code Playgroud)


Ser*_*nyy 5

除了\r\b方法之外,还可以使用\033[2K 控制字符,它告诉终端清除整行。与此相比,这样做的优点\b是您不必将\b要删除的字符数与要删除的字符数相匹配,并且\r如果新行比旧行短,则不会有字符在屏幕上突出一。

下面是如何将其应用于此问题的示例,下面是相关应用程序的示例,用于创建类似于启动消息的输出。在此特定示例中,一旦到达第 0 秒,计时器就会消失,并且计时器行将替换为“Ready!” 短语。

#!/bin/bash
sek=60
echo "60 Seconds"

while ((sek--)); do
    printf "One moment please: %d" "$sek"
    sleep 1
    printf "\r%b" "\033[2K"
done
echo "Ready!"
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用dialog命令在命令行中创建简单的对话框。该对话框将在计时器持续时间内保留在屏幕上,并随着循环进行更新,到完成时 - 计时器将以无缝方式替换为“就绪!按退出”消息:

#!/bin/bash
sek=60
echo "60 Seconds"

while ((sek--)); do
    echo "$sek" | dialog --progressbox "Please wait" 10 25
    sleep 1
done
dialog --msgbox "Ready! Press <OK> to finish" 10 25
Run Code Online (Sandbox Code Playgroud)