Nach dem Lesen von 24.2. Lokale Variablen Ich dachte, dass das Deklarieren einer Variablen var
mit dem Schlüsselwort local
bedeutet, dass auf var
den Wert nur innerhalb des Codeblocks zugegriffen werden kann, der durch die geschweiften Klammern einer Funktion begrenzt wird.
Doch nach dem folgende Beispiel ausgeführt wird , fand ich , dass aus var
auch zugegriffen werden kann, lesen und von den Funktionen , die durch diesen Block von Code aufgerufen geschrieben - dh auch wenn var
erklärt wird , local
zu outerFunc
, innerFunc
ist noch in der Lage , es zu lesen und seinen Wert zu verändern.
#!/usr/bin/env bash
function innerFunc() {
var='new value'
echo "innerFunc: [var:${var}]"
}
function outerFunc() {
local var='initial value'
echo "outerFunc: before innerFunc: [var:${var}]"
innerFunc
echo "outerFunc: after innerFunc: [var:${var}]"
}
echo "global: before outerFunc: [var:${var}]"
outerFunc
echo "global: after outerFunc: [var:${var}]"
Ausgabe:
global: before outerFunc: [var:] # as expected, `var` is not accessible outside of `outerFunc`
outerFunc: before innerFunc: [var:initial value]
innerFunc: [var:new value] # `innerFunc` has access to `var` ??
outerFunc: after innerFunc: [var:new value] # the modification of `var` by `innerFunc` is visible to `outerFunc` ??
global: after outerFunc: [var:]
F: Ist das ein Fehler in meiner Shell (bash 4.3.42, Ubuntu 16.04, 64bit) oder ist es das erwartete Verhalten?
EDIT: Gelöst. Wie von @MarkPlotnick festgestellt, ist dies in der Tat das erwartete Verhalten.
var
leer ist?var
ist global festgelegt.innerFunc
Warum bleibt sie also nicht bis zum Ende des Skripts erhalten?Antworten:
Shell-Variablen haben einen dynamischen Gültigkeitsbereich . Wenn eine Variable als lokal für eine Funktion deklariert wird, bleibt dieser Bereich bestehen, bis die Funktion zurückgegeben wird.
Es gibt zwei Ausnahmen:
Wenn in ksh93 eine Funktion mit der Standardsyntax definiert
function_name () { … }
ist, gehorchen ihre lokalen Variablen dem dynamischen Gültigkeitsbereich. Wenn eine Funktion mit der ksh-Syntax definiert ist, unterliegtfunction function_name { … }
ihre lokale Variable dem lexikalischen / statischen Gültigkeitsbereich, sodass sie in anderen von dieser Funktion aufgerufenen Funktionen nicht sichtbar sind.Das automatisch ladbare
zsh/private
Pluginzsh
bietet einprivate
Schlüsselwort / Builtin, mit dem eine Variable mit statischem Gültigkeitsbereich deklariert werden kann.ash, bash, pdksh und derivate, bosh haben nur dynamisches scoping.
quelle
local
?typeset
oderdeclare
oderlocal
Deklaration bleibt der Gültigkeitsbereich solange bestehen, bis die Funktion zurückkehrt. Ohne eine solche Erklärung ist der Geltungsbereich global.Es ist kein Fehler, der Aufruf innerhalb des Kontexts der OuterFunc verwendet diese lokale Kopie von $ var. Das "lokale" in OuterFunc bedeutet, dass das globale nicht geändert wird. Wenn Sie innerFunc außerhalb von outerFunc aufrufen, wird die globale $ var geändert, nicht jedoch die lokale $ var der outerFunc. Wenn Sie innerFunc "local" hinzufügen, wird $ var von outerFunc nicht geändert - im Wesentlichen gibt es drei davon:
Um das Namespace-Format von Perl zu verwenden, verwenden Sie eine Art.
quelle
Sie können eine Funktion verwenden, um den lokalen Bereich zu erzwingen:
Beispiel:
Ergebnis:
Quelle
quelle
In
function innerFunc()
demvar='new value'
nicht wie erklärt wurde , lokal , deshalb ist es im sichtbaren Bereich zur Verfügung (wenn die Funktion aufgerufen wurde).Im Gegensatz dazu in
function outerFunc()
demlocal var='initial value'
wie erklärt wurde , lokal , deshalb ist es nicht im globalen Bereich (auch wenn die Funktion aufgerufen wurde).Da var
innerFunc()
als Kind von aufgerufen wurdeouterFunc()
, liegt es im lokalen Geltungsbereich vonouterFunc()
.man 1 bash
kann helfen zu klärenDas implizite Verhalten, das in der Beschreibung erwartet wird, kann durch Deklaration von
local var='new value
in erreicht werdenfunction innerFunc()
.Wie andere gesagt haben, ist dies kein Fehler in der Bash-Shell. Alles funktioniert wie es sollte.
quelle
var
im globalen Bereich, nach dem AufrufinnerFunc
durchoutFunc
, druckt nichtnew value
.