Bash-Variablen initialisieren - Wird es benötigt, empfohlen oder definiert, wenn Sie fortfahren?

10

Gibt es einen Vor- oder Nachteil beim Initialisieren des Werts einer Bash-Variablen im Skript, entweder vor dem Hauptcode, oder lokaler Variablen in einer Funktion, bevor der tatsächliche Wert zugewiesen wird?

Muss ich so etwas tun:

init()
{
    name=""
    name=$1
}

init "Mark"

Besteht das Risiko, dass Variablen mit Müllwerten initialisiert werden (falls nicht initialisiert) und sich dies negativ auf die Werte der Variablen auswirkt?

Cyrus
quelle
1
Woher hast du diese Idee?
6
@DoritoStyle Nun, wenn man es gewohnt ist, Sprachen auf niedrigerer Ebene wie C zu verwenden, dann ist dies eine absolut gültige Sache, über die man sich Sorgen machen muss.
Kusalananda

Antworten:

21

Es hat keinen Vorteil, einer Variablen eine leere Zeichenfolge zuzuweisen und ihr dann sofort eine andere Variablenzeichenfolge zuzuweisen. Durch die Zuweisung eines Werts zu einer Shell-Variablen wird der vorherige Wert vollständig überschrieben.

Meines Wissens gibt es keine Empfehlung, die besagt, dass Sie Variablen explizit auf leere Zeichenfolgen initialisieren sollten. In der Tat kann dies unter bestimmten Umständen Fehler maskieren (Fehler, die ansonsten bei Ausführung unter auftreten würden set -u, siehe unten).

Eine nicht gesetzte Variable, die seit dem Start eines Skripts nicht mehr verwendet oder durch Ausführen des unsetBefehls explizit deaktiviert wurde , hat keinen Wert. Der Wert einer solchen Variablen ist nichts. Bei Verwendung als erhalten "$myvariable"Sie das Äquivalent von "".

Wenn die Shell-Option nounsetmit entweder set -o nounsetoder festgelegt ist set -u, führt das Verweisen auf eine nicht gesetzte Variable dazu, dass die Shell einen Fehler erzeugt (und eine nicht interaktive Shell beendet wird):

$ set -u
$ echo "$myvariable"
/bin/sh: myvariable: parameter not set

oder in bash:

$ set -u
$ echo "$myvariable"
bash: myvariable: unbound variable

Shell-Variablen werden von der Umgebung initialisiert, wenn der Name der Variablen einer vorhandenen Umgebungsvariablen entspricht.

Wenn Sie erwarten, dass Sie eine Variable verwenden, die möglicherweise von der Umgebung auf diese Weise initialisiert wird (und wenn dies unerwünscht ist), können Sie sie vor dem Hauptteil Ihres Skripts explizit deaktivieren:

unset myvariable    # unset so that it doesn't inherit a value from the environment

Dadurch wird es auch als Umgebungsvariable entfernt, oder Sie können den Anfangswert einfach ignorieren und es einfach mit einer Zuweisung überschreiben (wodurch sich auch der Wert der Umgebungsvariablen ändert).

In einer Shell-Variablen würden Sie niemals auf nicht initialisierten Müll stoßen (es sei denn, wie angegeben, dieser Müll war bereits in einer Umgebungsvariablen mit demselben Namen vorhanden).

Kusalananda
quelle
3
Während es keinen Wert gibt, eine Variable auf einen leeren Wert zu setzen und sie dann sofort so einzustellen, wie es das OP buchstäblich tut, ist es sinnvoll, einen leeren Wert (oder unsetTing) festzulegen, bevor eine Art foroder whileSchleife ausgeführt wird, um sie auf einen berechneten Wert zu setzen Wert, wenn die Möglichkeit besteht, dass die Schleife aufgrund der nicht erfüllten Bedingung (en) nicht ausgeführt wird; und die Variable wurde möglicherweise auf einen anderen Wert in der Umgebung gesetzt, die das Skript geerbt hat. Aber es ist wohl besser, alles in a zu setzen main()und die Variablen als zu definieren local.
Monty Harder
Sie können auch nicht gesetzte Variablen mithilfe der Parametererweiterungsoperatoren erkennen, indem Sie :z. B.${myvariable-defaultvalue}
Barmar
2

Das Deklarieren lokaler Variablen in einer Funktion hat den Vorteil, dass Sie den Code problemlos kopieren können.

Angenommen, ich habe eine Funktion in meiner .bashrc:

foo(){
    local name
    name="$1"
    echo "$name"
}

Wenn ich daraus ein Skript machen möchte, ignoriere ich einfach die localAnweisung und kopiere alles andere:

#!/bin/bash
name="$1"
echo "$name"

Wenn die Deklaration und die Zuordnung in derselben Zeile wären, müsste ich das localTeil manuell bearbeiten, bevor ich es in ein Skript umwandeln könnte:

foo(){
    local name="$1"
    echo "$name"
}

In diesem Beispiel ist es keine große Sache, aber wenn Sie mit größeren, komplexeren Funktionen arbeiten, kann es schmerzhafter werden.

wjandrea
quelle
Es ging nicht darum, die Deklaration und die Initialisierung zu kombinieren. Es ging darum, ob mit einem leeren Wert initialisiert werden soll, bevor ein realer Wert zugewiesen wird.
Barmar
@Barmar Oh, ich habe gerade "Initialisierung" nachgeschlagen. Ich dachte, es sei gleichbedeutend mit "Erklärung" ...
wjandrea