忽略或捕捉除以零

忽略或捕捉除以零

如何忽略 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)

相关内容