bash -e esce quando let o expr vengono valutati su 0


19

Ho uno script bash che imposta -e quindi lo script uscirà con qualsiasi stato di uscita! = 0.

Sto provando a fare un po 'di aritmetica della shell di base assegnata alle variabili e talvolta l'espressione è uguale a 0, il che fa sì che lo stato di uscita del comando let o expr sia "1".

Ecco un esempio:

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

L'output è:

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

La mia domanda è qual è il modo di scripting bash idiomatico per consentire allo script di fallire su errori di uscita reali e non su un'aritmetica di base uguale a 0. Potrei aggiungere a tutte quelle espressioni il suffisso:

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

Ma sembra disordinato.

Risposte:


16

Non usare exprper l'aritmetica. È stato a lungo obsoleto: le shell ora hanno l'aritmetica incorporata, con il $((…))costrutto (POSIX), o con letbuiltin (ksh / bash / zsh) o il ((…))costrutto (ksh / bash / zsh).

lete ((…))restituisce 1 (un codice di stato di errore) se l'ultima espressione valutata è 0. Per evitare che ciò causi la chiusura dello script in set -e, fare in modo che l'ultima espressione non restituisca 0, ad esempio:

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

In alternativa, usa il || truelinguaggio:

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

In alternativa, esegui l'aritmetica all'interno $((…))e i compiti all'esterno. Un'assegnazione restituisce lo stato dell'ultima sostituzione del comando nel valore o 0 se non vi è alcuna sostituzione del comando, quindi sei al sicuro. Ciò ha l'ulteriore vantaggio di lavorare in qualsiasi shell POSIX (come il trattino).

a=$((2 - 2))

1

Usa $(( $C - $D ))invece per il tuo aritmico. È anche più efficiente.


Cosa lo rende più efficiente di quanto si dica (( A = $C - $D ))?
vescovo,

1

Ho avuto lo stesso problema . tl; dr:

Se l'ultimo ARG [di let] restituisce 0, let restituisce 1; let restituisce 0 altrimenti.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.