setze -u Verwendung funktioniert nicht wie erwartet


12

Ich lerne, wie ich verschiedene setOptionen in meinem Skript effizient nutzen kann , und bin darauf gestoßen, set -udass dies perfekt zum Beenden meines Skripts ist, wenn eine Variable nicht richtig festgelegt wird (z. B. Löschen von Benutzern). Nach dem Mann Seite, set -uund set -ehat die folgende ...

-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" anzeigt und dann fehlschlägt, da ${testing2}es nicht festgelegt ist.

Stattdessen wird 0 und "Dies funktioniert" angezeigt , gefolgt von 0 und dann 0 Dies sollte nicht angezeigt werden

Kann jemand etwas Wissen vermitteln? Vielen Dank.


1
Also Follow-up ... gibt es eine Möglichkeit, das Setzen einer Variablen auf die Nullzeichenfolge unzulässig zu machen / einen Fehler auszulösen? Ich vermute nicht.
Luke Davis

Antworten:


10

Aus "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 dies tun, setzen testing2=Sie die Variable auf die Nullzeichenfolge.

Ändern Sie das in unset testing2und versuchen Sie es erneut.


Das set -ehilft nicht , in diesem Fall als eine Zuordnung nie einen Exit - Code von 1. Versuchen Sie dieses zu sehen ist , dass der letzte Befehl ausgeführt (die Zuweisung) hat einen Exit - Code von 0 oder diese Frage lesen :

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

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

Bei der Verwendung nicht festgelegter Variablen kann ein Fehler auftreten set -u:

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

Wird ausgegeben:

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

3

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

Wenn Sie jedoch echo $testing99in einer interaktiven Bash-Shell (ohne Einstellung errexit, dh set -e) ausgeführt werden, wird folgende Fehlermeldung angezeigt:

bash: testing99: unbound variable

Beiseite

Beim Testen von Skripten habe ich festgestellt, dass eine interaktive Shell nicht immer beendet wird, wenn versucht wird, eine Variable zu erweitern, die nicht festgelegt wurde, während eine nicht interaktive Shell (die ein Shell-Skript ausführt) immer beendet wird . Laut der POSIX-Manpage für set:

-u Die Shell muss eine Nachricht in den Standardfehler schreiben, wenn sie versucht, eine nicht gesetzte Variable zu erweitern und sofort zu beenden. Eine interaktive Shell darf nicht beendet werden.

Eine interaktive Bash-Shell wird erst beendet, wenn errexitsie ebenfalls festgelegt wurde. Auf der anderen Seite wird eine interaktive Dash-Shell nicht beendet - selbst wenn set -esie zuvor ausgeführt wurde.


Wenn der Bindestrich nicht mit set -e beendet wird; set -u; nicht gesetzt aa; echo $ aa, dann ist dash falsch.
schily

@schily Als ich dies zum ersten Mal bemerkte, stellte ich fest, dass die Dash-Autoren es besser wussten als ich und dass die POSIX-Spezifikationen möglicherweise nicht eindeutig waren, aber pubs.opengroup.org/onlinepubs/9699919799/utilities/… , I erneut überprüft hatten stimme zu, das sieht aus wie ein Bug, okay.
Anthony Geoghegan

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.
schily
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.