Mam skrypt bash, który ustawia -e, więc skrypt zakończy działanie przy każdym statusie wyjścia! = 0 .
Próbuję wykonać jakąś podstawową arytmetykę powłoki przypisaną do zmiennych, a czasami wyrażenie jest równe 0, co powoduje, że kod zakończenia polecenia let lub wyrażenie wynosi „1”.
Oto przykład:
#!/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"
Wynik to:
$ ./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"
Mój Pytanie brzmi: jaki jest idiomatyczny sposób tworzenia skryptów bash, który pozwala skryptowi zawieść przy prawdziwych błędach wyjścia, a nie przy podstawowej arytmetyce równej 0. Mogę dodać do wszystkich tych wyrażeń:
A=`expr $C - $D` || true
Ale wydaje się, że to zepsuty.
Odpowiedź
Nie używaj expr
dla arytmetyki. Od dawna jest przestarzały: powłoki mają teraz wbudowaną arytmetykę, z konstrukcją $((…))
(POSIX) lub z wbudowanym let
(ksh / bash / zsh) lub konstrukcją ((…))
(ksh / bash / zsh).
let
i ((…))
zwraca 1 (kod statusu błędu), jeśli ostatnim ocenianym wyrażeniem jest 0. Aby uniknąć tego powodu, że skrypt zakończy działanie w set -e
, ustaw ostatnie wyrażenie nie zwracające 0, na przykład:
let "a = 2 - 2" 1 ((a = 2 - 2, 1))
Alternatywnie użyj idiomu || true
:
((a = 2 - 2)) || true
Możesz też wykonać arytmetykę wewnątrz $((…))
i zadania na zewnątrz. Przypisanie zwraca status ostatniego podstawienia polecenia w wartości lub 0, jeśli nie ma podstawienia polecenia, więc jesteś bezpieczny. Ma to dodatkową zaletę pracy w dowolnej powłoce POSIX (takiej jak myślnik).
a=$((2 - 2))
Odpowiedź
Miałem ten sam problem . tl; dr:
Jeśli ostatnia wartość ARG [of let] wynosi 0, niech zwraca 1; w przeciwnym razie zwraca 0 .
Odpowiedź
Użyj $(( $C - $D ))
zamiast dla Twojej arytmatyki. Jest też bardziej wydajne.
Komentarze
Odpowiedź
U mnie działa ta składnia:
a=$((b + c))
(( A = $C - $D ))
?