bash -e wird beendet, wenn let oder expr auf 0 ausgewertet werden

19

Ich habe ein Bash-Skript, das -e setzt, damit das Skript bei jedem Exit-Status beendet wird! = 0.

Ich versuche, eine grundlegende Shell-Arithmetik auszuführen, die Variablen zugewiesen ist, und manchmal ist der Ausdruck gleich 0, was bewirkt, dass der Beendigungsstatus des Befehls let oder expr "1" ist.

Hier ist ein Beispiel:

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

Die Ausgabe ist:

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

Meine Frage ist, wie man es mit idiomatischen Bash-Skripten schafft, dass das Skript bei echten Exit-Fehlern und nicht bei einer Grundrechenart von 0 fehlschlägt. Ich könnte all diese Ausdrücke mit folgendem Suffix versehen:

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

Aber das scheint verrückt zu sein.

Dougnukem
quelle

Antworten:

16

Nicht exprzum Rechnen verwenden. Es ist schon lange veraltet: Shells haben jetzt eine integrierte Arithmetik mit dem $((…))Konstrukt (POSIX) oder mit dem letKonstrukt (ksh / bash / zsh) oder mit dem ((…))Konstrukt (ksh / bash / zsh).

letund ((…))geben Sie 1 (einen Fehlerstatuscode) zurück, wenn der zuletzt ausgewertete Ausdruck 0 ist. Um zu vermeiden, dass Ihr Skript unter beendet wird set -e, sorgen Sie dafür, dass der letzte Ausdruck nicht 0 zurückgibt. Beispiel:

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

Verwenden Sie alternativ die || trueRedewendung:

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

Alternativ können Sie Ihre Arithmetik innerhalb $((…))und Ihre Aufgaben außerhalb ausführen. Eine Zuweisung gibt den Status der letzten Befehlsersetzung im Wert oder 0 zurück, wenn keine Befehlsersetzung erfolgt, sodass Sie sicher sind. Dies hat den zusätzlichen Vorteil, dass Sie in jeder POSIX-Shell (z. B. dash) arbeiten können.

a=$((2 - 2))
Gilles 'SO - hör auf böse zu sein'
quelle
1

Verwenden Sie $(( $C - $D ))stattdessen für Ihre Arithmetik. Es ist auch effizienter.

tylerl
quelle
Was macht es effizienter als zu sagen (( A = $C - $D ))?
Bischof
1

Ich hatte das gleiche Problem . tl; dr:

Wenn das letzte ARG [von let] 0 ergibt, gibt let 1 zurück. let gibt sonst 0 zurück.

l0b0
quelle
1

Diese Syntax funktioniert für mich:

a=$((b + c))
Mark Sawers
quelle