2017-01-20 2 views
3

Anmerkung der Redaktion:
Vielleicht ist die folgende, aus den eigenen Antwort genommen der OP, besser veranschaulicht das überraschende Verhalten:
f() { local b=1; g; echo $b; }; g() { b=2; }; f # -> '2'
Ie, g() konnte die f()lokale$b Variable ändern.
Variablenzuweisung in Call verschachtelter Funktion ändert unerwartet lokalen Variable im Gültigkeitsbereich des Anrufers


In Zsh und Bash, wenn ich die folgende Funktion f() { a=1; g; echo $a; } und die folgende Funktion g() { a=2; } wenn ich f laufen haben, bekomme ich die folgende Ausgabe statt der erwarteten: Es

$ f 
2 

Ist Wie auch immer, um diese Variable blutethrough von Funktion zu Funktion zu deaktivieren?

Ich arbeite an einem ziemlich großen und wichtigen Bash/Zsh-Skript bei der Arbeit, die eine Tonne von Variablen in verschiedenen Funktionen verwendet; viele dieser Funktionen hängen von einer größeren Master-Funktion ab, aber wegen der Variablen, die durch ein ziemlich unglückliches und unerwartetes Verhalten bluten, und Bugs sind in den Vordergrund gerückt, was mich daran hindert, die Entwicklung voranzutreiben, da ich dieses seltsame Problem zuerst ansprechen möchte .

Ich habe sogar versucht, mit local Variablen zu lokalisieren, aber der Effekt tritt immer noch auf.

BEARBEITEN: Beachten Sie, dass meine Frage nicht geht, wie Sie lokale Variablen verwenden, um das Durchlaufen von Variablen zu verhindern oder wie lokale Variablen funktionieren, wie Sie lokale Variablen setzen, wie Sie einer bereits deklarierten lokalen Variablen einen neuen Wert zuweisen. oder irgendwas von diesem Mist: Es geht darum, zu verhindern, dass Variablen in den Bereich von Anrufer/angerufenen Funktionen gelangen.

+1

Mögliches Duplikat [assign lokalen Variable von der Funktion in linux bash einer neuer Wert] (http://stackoverflow.com/questions/22527325/assign-local-variable-von-funktion-in-linux-bash-a-new-value) – Inian

+0

@Inisch, vielleicht, aber meine Frage hat wirklich nichts damit zu tun, einen neuen Wert zu geben eine Variable so sehr wie die alte beibehalten. Ich habe die akzeptierte Antwort und die eigentliche Frage in der von Ihnen verknüpften Frage durchgesehen und sie scheinen mein Problem nicht wirklich anzugehen. –

Antwort

5

Mit local erzeugt eine Variable Das wird nicht vom übergeordneten Bereich übernommen.

Es gibt nützliche Dinge hinzuzufügen.

Eine lokale Variable wird vererbt (und kann geändert werden), wenn die deklarierende Funktion eine andere Funktion aufruft. local schützt daher Änderungen an einer Variablen desselben Namens, die von höher im Gültigkeitsbereich geerbt wurde, aber nicht niedriger im Gültigkeitsbereich. Die Deklaration local muss daher auf jeder Ebene verwendet werden, es sei denn, Sie möchten den Wert im übergeordneten Bereich tatsächlich ändern. Dies steht im Gegensatz zu dem, was die meisten Programmiersprachen tun würden, und hat Vorteile (schnelle und schmutzige Datenfreigabe), erzeugt jedoch schwierig zu debuggende Fehlermodi.

Eine lokale Variable kann mit local -x exportiert werden, um sie für Unterprozesse nutzbar zu machen (ziemlich nützlich), oder nur bei der Erstellung mit local -r.

Ein netter Trick ist, dass Sie eine Variable mit dem Wert aus dem übergeordneten Bereich zum Zeitpunkt der Erstellung geerbt initialisieren können:

local -r VAR="$VAR" 

Wenn, wie ich, Sie immer set -u verwenden lautlos nicht initialisierten Variablen zu vermeiden, und kann nicht sicher sein, die variablen bereits belegt sind, können Sie dies mit einem leeren Wert zu initialisieren verwenden, wenn es nicht im übergeordneten Bereich definiert ist:

local -r VAR="${VAR-}" 
+0

Große Antwort. Als kleiner Punkt von Interesse: "Strich", "Bash" und "Zsh" alle verhalten sich so, wie Sie in Bezug auf die Vererbung beschreiben, während "ksh" der einzige Dissident ist (abgesehen davon, dass er die Funktion {... } 'Syntax anstelle von' () {...} 'und' typeset' anstelle von 'local'), wodurch lokale Variablen wirklich lokal sind. Die Methode zum Initialisieren einer lokalen Variable mit dem vererbten Wert funktioniert jedoch in allen von ihnen. – mklement0

1

Ich fühle mich wie ein Idiot für das nicht früher zu realisieren; Ich gehe voran gehen und diese Frage posten & sowieso, falls andere scheuert beantworten wie ich das gleiche Problem auftreten: Sie müssen erklären beide Variablen als lokale:

f() { local b=1; g; echo $b; } 
g() { b=2; } 
f 
# output: 2 

f() { local b=1; g; echo $b; } 
g() { local b=2; } 
f 
# output: 1 
Verwandte Themen