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
Counting down in a loop to zero by the number being given
提问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 to0
. - As for why
1
is printed first: that's simply due to theecho $#
statement beforethewhile
loop.
- 您需要运算符
-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!'
${1?No parameters given}
is an instance of shell parameter expansionbash
shell arithmetic is documented here.
${1?No parameters given}
是shell参数扩展的一个实例bash
shell 算法记录在这里。
回答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 seq
which 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 test
line 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 sleep
value 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
$COUNT
in your expression. You also should declare -i COUNT=$1
to 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"