impostare -u l'utilizzo non funziona come previsto


12

Sto imparando come utilizzare in modo efficiente diverse setopzioni nel mio script e mi sono imbattuto in set -uquello che sembra perfetto per uscire dal mio script se una variabile non viene impostata correttamente (es. Eliminazione degli utenti). Secondo la pagina man , set -ue set -efa quanto segue ...

-e  Exit immediately if a command exits with a non-zero status.
-u  Treat unset variables as an error when substituting.

Ho creato uno script di test per testare questa funzionalità, ma non sembra funzionare come previsto. Forse qualcuno potrebbe spiegarmi meglio il mio problema e dove sto interpretando male? Lo script di prova è di seguito. Grazie.

set -e
set -u
testing="This works"
echo $?
echo ${testing}
testing2=
echo $?
echo ${testing2}
testing3="This should not appear"
echo $?
echo ${testing3}

Mi aspetto che lo script visualizzi 0 e "Funziona" , quindi non riesco perché ${testing2}non è impostato.

Invece sono visualizzato 0 e "Funziona" , segui da 0 e quindi 0 Questo non dovrebbe apparire

Qualcuno può fornire qualche conoscenza? Grazie.


1
Quindi follow-up ... c'è un modo per rendere illegale l'impostazione di una variabile sulla stringa nulla / generare un errore? Immagino di no.
Luke Davis,

Risposte:


10

Da "man Bash":

Un parametro viene impostato se è stato assegnato un valore. La stringa null è un valore valido. Una volta impostata una variabile, può essere disinserita solo usando il comando incorporato unset.

Quando lo fai, testing2=stai impostando la variabile sulla stringa null.

Cambialo in unset testing2e riprova.


In set -equesto caso non aiuta in quanto un'assegnazione non ha mai un codice di uscita 1. Prova a vedere che l'ultimo comando eseguito (l'assegnazione) ha un codice di uscita di 0 o leggi questa domanda :

$ false; a=""; echo $?
0

E credo anche che l'uso di set -e sia più un problema che una soluzione.

Ciò che può ottenere un errore con l'uso di variabili non impostate è set -u:

#!/bin/bash
set -u
testing="This works"
echo ${testing}
unset testing2
echo ${testing2}
testing3="This should not appear"
echo ${testing3}

Uscita:

$  ./script.sh
This works
./script.sh: line 9: testing2: unbound variable

3

testing2=imposta la testing2variabile su una stringa vuota; la variabile è effettivamente impostata .

Tuttavia, se si eseguisse echo $testing99in una shell Bash interattiva (senza impostazione errexit, ovvero set -e), si otterrebbe un errore:

bash: testing99: unbound variable

A parte

Durante il test degli script proprio ora, ho scoperto che una shell interattiva non esce sempre quando si tenta di espandere una variabile che non è stata impostata mentre una shell non interattiva (che esegue uno script di shell) esce sempre . Secondo la pagina man POSIX per set:

-u La shell deve scrivere un messaggio di errore standard quando tenta di espandere una variabile che non è impostata e termina immediatamente. Una shell interattiva non deve uscire.

Un Bash shell interattiva non terminerà meno errexitè anche stato impostato. D'altra parte, una dash dash interattiva non verrà chiusa, anche se set -eè stata precedentemente eseguita.


Se il trattino non termina con set -e; set -u; disinserito aa; echo $ aa, quindi trattino è sbagliato.
schily

@schily Quando l'ho notato per la prima volta, ho pensato che gli autori di trattini sapessero meglio di me e che potesse esserci stata qualche ambiguità nelle specifiche POSIX ma aver ricontrollato pubs.opengroup.org/onlinepubs/9699919799/utilities/… , I d'accordo che sembra un bug, va bene.
Anthony Geoghegan

C'è una semplice regola: quando Korn Shell e Bourne Shell sono d'accordo e un'altra implementazione della shell ha una deviazione, l'altra shell si comporta in modo errato.
schily
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.