bash 通过给定的数字在循环中倒计时到零

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29720579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 12:49:59  来源:igfitidea点击:

Counting down in a loop to zero by the number being given

bashshellunixif-statementeco

提问by Mark

I am trying to write a while loop to determine the number is being given to count down to 0.

我正在尝试编写一个 while 循环来确定正在给倒计时到 0 的数字。

回答by mklement0

@Slizzered has already spotted your problem in a comment:

@Slizzered 已经在评论中发现了您的问题:

  • You need operator -ge(greater than or equal) rather than -gt(greater than) in order to count down to 0.
  • As for why 1is printed first: that's simply due to the echo $#statement beforethe whileloop.
  • 您需要运算符-ge(大于或等于)而不是-gt(大于)才能倒计时到0
  • 至于为什么1先打印:那只是由于循环之前echo $#语句。while


If you're using bash, you could also consider simplifying your code with this idiomatic reformulation:

如果您正在使用bash,您还可以考虑使用以下惯用的重新表述来简化您的代码:

#!/usr/bin/env bash

# Count is passed as the 1st argument.
# Abort with error message, if not given.
count=${1?No parameters given}

# Count down to 0 using a C-style arithmetic expression inside `((...))`.
# Note: Increment the count first so as to simplify the `while` loop.
(( ++count )) 
while (( --count >= 0 )); do
  echo $count
done

echo 'Finished!'

回答by geirha

You should also validate the variable before using it in an arithmetic context. Otherwise, a user can construct an argument that will cause the script to run in an infinite loop or hit the recursion limit and segfault.

您还应该在算术上下文中使用它之前验证变量。否则,用户可以构造一个参数,导致脚本在无限循环中运行或达到递归限制和段错误。

Also, don't use uppercase variable names since you risk overriding special shell variables and environment variables. And don't use [in bash; prefer the superior [[and ((constructs.

另外,不要使用大写的变量名,因为你可能会覆盖特殊的 shell 变量和环境变量。并且不要[在 bash 中使用;更喜欢上级[[((构造。

#!/usr/bin/env bash
shopt -s extglob     # enables extended globs

if (( $# != 1 )); then
    printf >&2 'Missing argument\n' 
    exit 1
elif [[  != +([0-9]) ]]; then
    printf >&2 'Not an acceptable number\n'
    exit 2
fi

for (( i = ; i >= 0; i-- )); do
    printf '%d\n' "$i"
done

# or if you insist on using while
#i=
#while (( i >= 0 )); do
#    printf '%d\n' "$((i--))"
#done

回答by leu

Your code is far from being able to run. So, I don't know where to start to explain. Let's take this small script:

你的代码远不能运行。所以,我不知道从哪里开始解释。让我们来看看这个小脚本:

#!/bin/sh

die() {
   echo  >&2
   exit 1;
}

test -z "" && die "no parameters given"
for i in $(seq  -1 0); do
   echo "$i"
done

The main part is the routine seqwhich does what you need: counting from start value to end value (with increment in between). The start value is $1, the parameter to our script, the increment is -1. The testline tests whether there is a parameter on the command line - if not, the script ends via the subroutine die.

主要部分是seq执行您需要的例程:从开始值到结束值计数(中间有增量)。起始值为$1,我们脚本的参数,增量为 -1。该test行测试命令行上是否有参数 - 如果没有,脚本通过 subroutine 结束die

Hth.

嗯。

回答by David C. Rankin

There are a number of ways to do this, but the general approach is to loop from the number given to an ending number decrementing the loop count with each iteration. A C-style for loopworks as well as anything. You will adjust the sleepvalue to get the timing you like. You should also validate the required number and type of input your script takes. One such approach would be:

有多种方法可以做到这一点,但一般的方法是从给定的数字循环到结束数字,每次迭代递减循环计数。一个C风格的for循环工程,以及任何东西。您将调整该sleep值以获得您喜欢的时间。您还应该验证脚本所需的输入数量和类型。一种这样的方法是:

#!/bin/bash

[ -n "" ] || {
    printf " error: insufficient input. usage:  %s number (for countdown)\n" "${0//*\//}"
    exit 1
}

[ "" -eq "" >/dev/null 2>&1 ] || {
    printf " error: invalid input. number '%s' is not an integer\n" ""
    exit 1
}

declare -i cnt=$(())

printf "\nLaunch will occur in:\n\n"

for ((i = cnt; i > 0; i--)); do

    printf " %2s\n" "$i"
    sleep .5

done

printf "\nFinished -- blastoff!\n\n"

exit 0

Output

输出

$ bash ./scr/tmp/stack/countdown.sh 10

Launch will occur in:

 10
  9
  8
  7
  6
  5
  4
  3
  2
  1

Finished -- blastoff!


Your Approach

你的方法

Your approach is fine, but you need to use the value of COUNT$COUNTin your expression. You also should declare -i COUNT=$1to tell the shell to treat it as an integer:

您的方法很好,但您需要COUNT$COUNT在表达式中使用的值。您还应该declare -i COUNT=$1告诉 shell 将其视为整数:

#!/bin/bash

if [ $# -eq "0" ] ;then
    echo "No paramters given"
else
    echo -e "\nNumber of arguments: $#\n\n"
fi

declare -i COUNT=

while [ $COUNT -gt 0 ] ;do
    echo $COUNT
    let COUNT=$COUNT-1
done
echo -e "\nFinished!\n"