Bash - 如何做一个普通的计数器?

Bash - 如何做一个普通的计数器?

所以我习惯做我所说的(不确定是否是正式名称)“计数器”,并且基本上执行涉及特定范围或数字的任务:

#!/bin/bash -x
get_total2=$(echo "$@")
while [ $get_total2 -gt 0 ]; do
    echo $get_total2
    get_total2=$(expr $get_total2 - 1)
done

使用的示例echo

但正如代码所示,它不是一个“正常”计数器(如按正常顺序),而是一个相反的计数器......我从来不知道如何做到这一点,尽管我确信它很容易,而且我'我只是想太多了。

我怎样才能使上面的代码以“正常”计数而不是相反的顺序工作?

答案1

您可以for在 bash 中使用循环来计数。例如,考虑:

#!/bin/bash -x

total="${1}"

for ((i = 0; i < total; ++i)); do
    echo "${i}"
done

如果我运行它,那么我会得到:

$ ./ex.sh 3
0
1
2
$

for循环的结构如下:

for ((init; condition; update))
  • init部分在循环开始之前运行一次,用于初始化变量。
  • condition每次通过循环都会评估该部分。当条件变为 时false,循环停止
  • update每次通过循环后都会评估 该部分。++i是一个简写形式i = i + 1

在这种情况下,您将通过循环获得以下步骤序列

  • i = 0
  • 0 < 3-> 正确
  • echo 0
  • ++i( i = i + 1) # i 变为 1
  • 1 < 3-> 正确
  • echo 1
  • ++i( i = i + 1) # i 变成 2
  • '2 < 3` -> 真
  • echo 2
  • ++i( i = i + 1) # i 变成 3
  • 3 < 3-> false # 循环终止

答案2

这里有四种选择,前两种用于 bash,一种向下,一种向上。
接下来的两个循环在 POSIX sh 中有效(在 bash 中也有效),
同样,一个是递减计数,一个是递增计数。

#!/bin/bash -

n=${1:-10}

       for ((i=n-1;i>=0;i--))        ; do    printf ' %s ' "$i"; done; echo
       for ((i=0;i<n;i++))           ; do    printf ' %s ' "$i"; done; echo

i=$n;  while [ "$((i-=1))" -ge "0"  ] ; do    printf ' %s ' "$i"; done; echo
i=-1;  while [ "$((i+=1))" -lt "$n" ] ; do    printf ' %s ' "$i"; done; echo

运行脚本的结果将是:

 9  8  7  6  5  4  3  2  1  0 
 0  1  2  3  4  5  6  7  8  9 
 9  8  7  6  5  4  3  2  1  0 
 0  1  2  3  4  5  6  7  8  9

演练

前两个循环使用 bash、ksh、zsh 中可用的 for 循环:

for (( start ; test ; execute )); do
  • 因此,将 的值设置n为第一个参数的值(如果存在),如果不存在则设置为 10。假设 n 设置为 10。

  • for 循环将i(计数器)设置为比$n:i=n-1或 9 小 1。

  • 测试部分被执行并且9>=0

  • printf 与iof一起执行99并被打印。

  • 循环的最后执行部分被执行并且 i 被减少i--

  • 循环再次测试,结果8是。>=0

  • printf 被执行,8 被打印。

  • i--执行,i变成7

  • 重复直到我们i成为0

  • 测试仍然为真,0>=0(在本例中等于)。

  • 打印0出来。

  • 在递减 上i--, i 变为-1且:

  • 现在测试失败-1的是不是 >=0

  • 循环已退出。

  • 执行最后echo一行,向下移动到下一行。

最终结果:9 比 0 打印在同一行:9 8 7 6 5 4 3 2 1 0

循环2

第二个循环就是您所要求的:上升循环。与上面的非常相似,但从 0 开始,到 9 结束。打印 `0 1 2 3 4 5 6 7 8 9`

循环3

  • n设置为 10(可以更改为脚本提供另一个参数)。
  • i被设置为该值i=$n
  • 当后面的测试 ( [...]) 为 true 时,执行 printf。
  • 在测试中,第一件事是减少iwith 1i-=1展开到i = i - 1. (i--在 中不可用sh)。这是在算术展开式中$((...))并被引用的(以避免 IFS 问题)。该算术扩展结果为9(并i为下一个循环保留该值)。
  • 对该值9进行数值比较-ge以确定它是否是G中继器或等于"0".
  • 与此一样9,printf 被执行并被打印。>="0"9
  • 循环重复,现在i9并减一到8
  • 仍会打印88 。>="0"
  • 重复直到i减少到0。由于测试仍然为真: 的值0仍然>=(在本例中等于)为"0"。 A0被打印。
  • 计数器减少到-1使测试失败的值,并且退出循环。

循环4

与上面几乎相同的循环,但向上计数。

答案3

像这样的东西应该有效:

#!/bin/bash -x
get_total2=$(echo "$@")
count=0
while [ $count -lt $get_total2 ]; do

    echo $count
    
count=$(expr $count + 1)
done

当出现提示时,您需要输入停止计数的数字。我可能有语法错误,但没有检查。也可能有更简单的方法来做到这一点。

答案4

其他一些变体,使用((i++))((++i))直接 while echoing


使用方括号:

#!/bin/bash

total="$1" i=0

echo -n "Using i++: "
while [ $i -lt $total ]; do echo -n " $((i++)) "; done; echo

i=0

echo -n "Using ++i: "
while [ $i -lt $total ]; do echo -n " $((++i)) "; done; echo

输出:

$ ./count.sh 5
Using i++:  0  1  2  3  4 
Using ++i:  1  2  3  4  5 

使用c-style

total="$1"
while (( i < total )); do
  echo -n " $((i++)) " # or " $((++i)) "
done; echo

# total: 5
# output i++: 0 1 2 3 4 
# output ++i: 1 2 3 4 5 

或者,您可以使用until

until (( i == total )); do echo -n " $((i++)) "; done; echo
# count.sh 5
# output: 0 1 2 3 4

一些解释:

echo $((i++))将先打印然后递增,而则echo $((++i))相反。

因此,如果您的x初始值为0,那么通过这样做,echo $((i++))它将打印0然后x变为1。证明:

$ echo $((x++))
0
$ echo $x
1
$ echo $((++x))
2
$ echo $x
2

相关内容