Bash 数学:计算一个数字是否可以被另一个数字整除时出现差一或错误

Bash 数学:计算一个数字是否可以被另一个数字整除时出现差一或错误

我使用了来自的解决方案这个答案在我正在编写的脚本中,但它似乎对我不起作用。我使用的是 Bash 5。这是一个简化的测试用例,我希望该do_thing函数在 5 的倍数的分钟内被调用(除非$min$minutes相同,因为在真实的脚本中,我在主程序do_thing开始时触发循环),但运行它也会触发这些倍数 + 1,所以显然我在某处有一点逐一或数学错误,但我没有看到它。有任何想法吗?

#!/usr/bin/env bash

minutes=6
sec=00
min="$minutes"

do_thing() {
  echo 'done thing'
}

while [ "$min" -ge 0 ]; do
  remainder=$(( min % 5 ))
  # TODO: this is broken
  [ "$remainder" -eq 0 ] && [ "$min" -ne "$minutes" ] && do_thing
  while [ $sec -ge 0 ]; do
    echo "$min $sec"
    ((sec=sec-1))
    sleep 1
  done
  sec=59
  ((min=min-1))
done

答案1

set -x调试任何 bash 脚本的第一件事就是在最顶部添加。这将让您看到脚本正在做什么、循环的每次迭代中的每个测试是什么样子等等。

这就是我要放的地方:

#!/usr/bin/env bash

# NOTE: Remove or comment the below line when you're done debugging!
set -x

minutes=6
sec=00
...

在调试时遍布echo "myvar = $myvar"整个代码还可以帮助您跟踪脚本中关键点的变量值,以便您可以将其与您认为应该的值进行比较。

你逻辑中的缺陷是,一旦你得到了让你退出“分钟计数器”循环的条件,你立即将 min 减少 1所以当你重新计算余数时,你总是会少一。你正在减少你的“计数器”你用它来进行你想要的计算!

从逻辑上讲,您想要测试秒= 0,然后计算余数,然后设置下一个循环:

#!/usr/bin/env bash

#set -x

minutes=6
sec=00
min="$minutes"

do_thing() {
  echo 'done thing'
}

while [ "$min" -ge 0 ]; do
  while [ $sec -ge 0 ]; do
    echo "$min $sec"
    ((sec=sec-1))
    sleep 1
  done
  remainder=$(( min % 5 ))
  # Added echo for debugging
  echo "remainder = $remainder"
  [ "$remainder" -eq 0 ] && [ "$min" -ne "$minutes" ] && do_thing
  sec=59
  ((min=min-1))
done

这里还有另一件事很突出——是非常小心使用&&and ||- 它们对于快速和肮脏来说很好,但是对于复杂的逻辑它们可以欺骗你!

这些逻辑运算符是不是适当测试的替代品,即使他们这样做有时- 与使用测试的一个区别if []; then...是它们会默默地消耗您的退出代码。仔细阅读它们,并且不要连续使用其中多个,而不使用它们()来强制执行您想要的操作顺序。

如果您想采纳我的建议并避免&&在这里,这里有一种方法(嵌套的 `if 是另一种方法,但如果不需要,我宁愿不使用它们):

  ...
  remainder=$(( min % 5 ))
  # Added echo for debugging
  echo "remainder = $remainder"
  if ([ "$remainder" -eq 0 ] && [ "$min" -ne "$minutes" ]); then
    do_thing
  fi
  sec=59
  ((min=min-1))
  ...

相关内容