Eu tenho um script bash que define -e para que o script saia em qualquer status de saída! = 0 .
Estou tentando fazer alguma aritmética de shell básica atribuída a variáveis e às vezes a expressão é igual a 0, o que faz com que o status de saída do comando let ou expr seja “1”.
Aqui está um exemplo:
#!/bin/bash -ex echo "Test 1" Z=`expr 1 - 1` || true echo "Z will print" let "A=4 - 4" echo "A WILL NEVER PRINT $A" Y=`expr 1 - 1` echo "Y WILL NEVER PRINT $Y" X=$(expr 2 - 2) echo "X WILL NEVER PRINT $X"
O resultado é:
$ ./test_error.sh + echo "Test 1" Test 1 ++ expr 1 - 1 + Z=0 + true + echo "Z will print" Z will print + let "A=4 - 4"
Meu a questão é qual é a maneira idiomática de script bash para permitir que o script falhe em erros reais de saída e não em aritmética básica igual a 0. Eu poderia sufocar todas essas expressões com:
A=`expr $C - $D` || true
Mas isso parece hacky.
Resposta
Não use expr
para aritmética. Está obsoleto há muito tempo: os shells agora têm aritmética incorporada, com a construção $((…))
(POSIX) ou com let
incorporada (ksh / bash / zsh) ou a construção ((…))
(ksh / bash / zsh).
let
e ((…))
retornar 1 (um código de status de falha) se a última expressão avaliada for 0. Para evitar que isso faça com que seu script saia em set -e
, organize para a última expressão não deve retornar 0, por exemplo:
let "a = 2 - 2" 1 ((a = 2 - 2, 1))
Como alternativa, use o || true
idioma:
((a = 2 - 2)) || true
Como alternativa, faça sua aritmética dentro de $((…))
e suas tarefas fora. Uma atribuição retorna o status da última substituição de comando no valor, ou 0 se não houver substituição de comando, então você está seguro. Isso tem a vantagem de trabalhar em qualquer shell POSIX (como o traço).
a=$((2 - 2))
Resposta
Eu tinha o mesmo problema . tl; dr:
Se o último ARG [de let] for avaliado como 0, let retorna 1; let retorna 0 caso contrário .
Resposta
Use $(( $C - $D ))
em vez de sua aritmática. É mais eficiente também.
Comentários
Resposta
Esta sintaxe funciona para mim:
a=$((b + c))
(( A = $C - $D ))
?