set -u Verwendung funktioniert nicht wie erwartet

Ich lerne, wie ich verschiedene set -Optionen in meinem Skript effizient verwenden kann und stieß auf set -u, das sich perfekt zum Beenden meines Skripts eignet, wenn eine Variable nicht richtig festgelegt wird (z. B. Löschen von Benutzern). Laut der Seite man set -u und set -e führt die folgenden Schritte aus …

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

Ich habe ein Testskript erstellt, um diese Funktionalität zu testen, aber es scheint nicht wie erwartet zu funktionieren . Vielleicht könnte mir jemand mein Problem besser erklären und wo ich falsch interpretiere? Testskript ist unten. Vielen Dank.

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

Ich erwarte, dass das Skript 0 und „Dies funktioniert“ und schlägt dann fehl, wie ${testing2} ist nicht festgelegt.

Stattdessen wird 0 und „Dies funktioniert“ , gefolgt von 0 und dann 0 Dies sollte nicht erscheinen

Kann jemand etwas Wissen vermitteln? Vielen Dank.

Kommentare

  • Also Follow-up … gibt es eine Möglichkeit, das Setzen einer Variablen auf die Nullzeichenfolge illegal zu machen / einen Fehler auszulösen? Ich ' rate nicht.

Antwort

From “ man Bash „:

Ein Parameter wird gesetzt, wenn ihm ein Wert zugewiesen wurde. Die Nullzeichenfolge ist ein gültiger Wert. Sobald eine Variable festgelegt wurde, kann sie nur mit dem Befehl unset builtin deaktiviert werden.

Wenn Sie testing2= Sie setzen die Variable auf die Nullzeichenfolge.

Ändern Sie diese in unset testing2 und versuchen Sie es erneut.


Die set -e hilft in diesem Fall nicht, da eine Zuweisung niemals einen Exit-Code von 1 hat. Versuchen Sie dies, um festzustellen, dass der zuletzt ausgeführte Befehl (die Zuweisung) einen Exit-Code von 0 oder lese diese Frage :

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

Und ich glaube auch, dass die Verwendung von set -e ist eher ein Problem als eine Lösung.

Was bei der Verwendung nicht festgelegter Variablen zu einem Fehler führen kann, ist set -u:

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

Gibt Folgendes aus:

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

Antwort

testing2= setzt die Variable testing2 auf eine leere Zeichenfolge. Die Variable ist tatsächlich gesetzt .

Wenn Sie jedoch echo $testing99 in einer interaktiven Bash-Shell ausführen (ohne errexit, dh set -e), würde eine Fehlermeldung angezeigt:

bash: testing99: unbound variable 

Neben

Beim Testen von Skripten habe ich festgestellt, dass eine interaktive Shell nicht immer beim Versuch, eine Variable zu erweitern, die nicht festgelegt wurde , während eine nicht interaktive Shell (mit einem Shell-Skript) beendet immer . Gemäß der POSIX-Manpage für set:

-u Die Shell muss eine Nachricht zum Standardfehler schreiben wenn versucht wird, eine nicht festgelegte Variable zu erweitern und sofort zu beenden. Eine interaktive Shell darf nicht beendet werden.

Eine interaktive Bash-Shell wird nur beendet, wenn errexit auch eingestellt. Andererseits wird eine interaktive Dash-Shell nicht beendet – selbst wenn zuvor set -e ausgeführt wurde.

Kommentare

  • Wenn der Bindestrich nicht mit set -e beendet wird; set -u; nicht gesetzt aa; Echo $ aa, dann ist Bindestrich falsch.
  • @schily Als ich dies zum ersten Mal bemerkte, stellte ich fest, dass die Bindestrichautoren es besser wussten als ich und dass die POSIX-Spezifikationen möglicherweise nicht eindeutig waren, aber erneut überprüft pubs.opengroup.org/onlinepubs/9699919799/utilities/… Ich stimme zu, dass dies wie ein Fehler aussieht. In Ordnung.
  • Es gibt eine einfache Regel: Wenn sowohl Korn Shell als auch Bourne Shell übereinstimmen und eine andere Shell-Implementierung eine Abweichung aufweist, verhält sich die andere Shell falsch.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.