bash -e sale cuando let o expr evalúa a 0

Tengo un script bash que establece -e para que el script salga en cualquier estado de salida! = 0.

Estoy tratando de hacer algunas aritméticas básicas de shell asignadas a las variables y, a veces, la expresión es igual a 0, lo que hace que el estado de salida del command let o expr sea "1".

Aquí hay un ejemplo:

#!/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" 

El resultado es:

 $ ./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' 

Mi pregunta es ¿cuál es la forma idiomática de bash scripting para permitir que el script falle en los errores de salida real y no en la aritmética básica que equivale a 0. Podría sufijo todas esas expresiones con:

 A=`expr $C - $D` || true 

Pero eso parece hacky.

No use expr para aritmética. Hace time que ha quedado obsoleto: las shells ahora tienen aritmética incorporada, con el constructo $((…)) (POSIX), o con el command let builtin (ksh / bash / zsh) o ((…)) (ksh / bash / zsh).

let y ((…)) return 1 (un código de estado de falla) si la última expresión evaluada es 0. Para evitar que esto provoque que su script salga bajo set -e , set -e arreglos para que la última expresión no devuelva 0, por ejemplo:

 let "a = 2 - 2" 1 ((a = 2 - 2, 1)) 

Alternativamente, usa el || true || true modismo:

 ((a = 2 - 2)) || true 

Alternativamente, haga su aritmética dentro de $((…)) y sus asignaciones fuera. Una asignación devuelve el estado de la última sustitución de command en el valor, o 0 si no hay sustitución de command, por lo que está a salvo. Esto tiene la ventaja adicional de trabajar en cualquier shell POSIX (como el guión).

 a=$((2 - 2)) 

Use $(( $C - $D )) para su aritmático. Es más eficiente también.

Tuve el mismo problema . tl; dr:

Si el último ARG [de let] se evalúa a 0, let returns 1; Deje devuelve 0 de lo contrario.