Ignorar ou pegar divisão por zero

5

Como eu ignoro a divisão por erro zero no Bash?

Exemplo 1: (não funciona)

echo $((1/0)); echo "yay";
echo $((1/0)) || echo "yay";

Exemplo 2:

echo -n $(echo -n $((1/0))) 2> /dev/null; echo "yay";

Existe uma maneira mais fácil do que o exemplo 2, que seria o padrão para um valor específico, quando uma divisão por zero é encontrada.

    
por Tyilo 30.12.2011 / 22:00

4 respostas

4

O Bash não tem como interceptar divisões por 0, nem ash, ksh93, pdksh ou zsh. As únicas maneiras de capturar as divisões por 0 são detectá-las antes que elas aconteçam (verificar todos os denominadores antes de realizar a divisão) ou fazê-las em uma subcamada.

Se você fizer a aritmética em um subshell, você pode usar o status de saída do subshell para saber se um erro (divisão por 0 ou outro) aconteceu.

x=$(echo $(($a/$b)))
if [ $? -ne 0 ]; then
  echo "$b is 0 or some other arithmetic error occurred"
fi
    
por 30.12.2011 / 23:46
1

bem, além de if (($divisor == 0)); then SHUT_DOWN_EVERYTHING; , acho que você poderia usar um subshell:

(echo $((1/0))) 2>/dev/null || echo yay

mas observe que isso silenciosamente está ignorando o erro como em seu código de exemplo, não é o que você pediu que seja um "valor padrão", então por que não explicar o que você está tentando fazer?

    
por 30.12.2011 / 22:51
0

SIGFPE (sinal número 8) é provavelmente o sinal que você tem que pegar aqui.

Instale um manipulador de sinal para esse:

trap "echo divide by zero >&2 ; exit 1 " SIGFPE

Atualização: parece que o bash tem seu próprio manipulador para isso que não pode ser substituído. Eu transferi a solução de um programa C simples para a sintaxe bash ...

Bem, esse método deve funcionar para outras armadilhas ...

    
por 30.12.2011 / 22:54
0

usamos uma pequena função em nossos scripts

#!/bin/sh
divisor_valid "$myvar" || myvar=1
x=$(( 1000 / myvar ))
y=$(( 1000 % myvar ))

Dessa forma, ainda é legível e evitamos o subgelo com uso intensivo de CPU.

as funções auxiliares são:

isnumber(){ test 2>/dev/null ${1:-a} -eq "${1##*[!0-9-]*}";}
divisor_valid(){ isnumber $1||return;case $1 in 0|-0)false;;esac;}

estamos usando o busybox-ash, mas ele deve funcionar (tm) no POSIX

    
por 19.11.2015 / 17:36

Tags