我在正在处理的脚本中使用了此答案中的解决方案,但它似乎不适用于我。我使用的是Bash5。这是一个简化的测试用例,我希望do_thing
函数在5的倍数处被调用(除了$min
和$minutes
相同时除外,因为在真实脚本中,我do_thing
是在main的开头触发的)循环),但运行它还会触发这些倍数+ 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
调试任何bash脚本的第一件事是set -x
在最顶部添加。这将使您看到脚本在做什么,在循环的每次迭代中每个测试的外观,等等。
这是我要放的地方:
#!/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,因此,当您重新计算其余部分时,总会减少1。你递减的“柜台”前,你使用它所需的计算!
从逻辑上讲,您要测试seconds = 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
另一件事在这里引人注目-请非常小心-&&
和||
-它们既方便又脏又好,但是对于复杂的逻辑,它们可能会欺骗您!
这些逻辑运算符有时不能以适当的方式代替,即使它们有时会以这种方式运行-与使用例如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))
...
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句