bash -e kończy działanie, gdy let lub expr zwraca wartość 0

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

  • Co sprawia, że jest bardziej wydajne niż powiedz (( A = $C - $D ))?

Odpowiedź

U mnie działa ta składnia:

a=$((b + c)) 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *