如何忽略 Bash 中除以零的错误?
示例1:(不起作用)
echo $((1/0)); echo "yay";
echo $((1/0)) || echo "yay";
示例2:
echo -n $(echo -n $((1/0))) 2> /dev/null; echo "yay";
有没有比示例 2 更简单的方法,当遇到被零除时,它会默认为特定值。
答案1
Bash 没有办法捕获除数为 0 的情况,ash、ksh93、pdksh 或 zsh 也没有。捕获除数为 0 的唯一方法是在除法发生之前检测它们(在执行除法之前检查每个分母)或在子 shell 中执行除法。
如果您在子 shell 中进行算术运算,则可以使用子 shell 的退出状态来了解是否发生了错误(除以 0 或其他错误)。
x=$(echo $(($a/$b)))
if [ $? -ne 0 ]; then
echo "$b is 0 or some other arithmetic error occurred"
fi
答案2
好吧,除了if (($divisor == 0)); then SHUT_DOWN_EVERYTHING;
我认为你可以使用子外壳:
(echo $((1/0))) 2>/dev/null || echo yay
但请注意,这是默默地忽略示例代码中的错误,这不是您所要求的“默认值”,所以为什么不解释一下您想要做什么呢?
答案3
SIGFPE(信号号 8)可能是您必须在此处捕获的信号。
为该信号安装一个信号处理程序:
trap "echo divide by zero >&2 ; exit 1 " SIGFPE
更新: bash 似乎有自己的处理程序,不能被覆盖。我将解决方案从普通的 C 程序转移到 bash 语法......
嗯 - 这个方法应该适用于其他陷阱......
答案4
我们在脚本中使用一个小函数
#!/bin/sh
divisor_valid "$myvar" || myvar=1
x=$(( 1000 / myvar ))
y=$(( 1000 % myvar ))
这样它仍然是可读的,并且我们避免了 CPU 密集型子 shell。
辅助函数是:
isnumber(){ test 2>/dev/null ${1:-a} -eq "${1##*[!0-9-]*}";}
divisor_valid(){ isnumber $1||return;case $1 in 0|-0)false;;esac;}
我们正在使用 busybox-ash,但它应该可以在 POSIX 上工作(tm)