A 24.2 elolvasása után. Helyi változók , úgy gondoltam, hogy egy var
változó deklarálása a local
kulcsszóval azt jelentette, hogy var
értéke csak a függvény göndör zárójelével határolt kódblokkban volt elérhető.
A következő példa futtatása után azonban kiderült, hogy var
is elérhetõ, olvasható és írható az adott kódblokk által meghívott függvényekbõl – annak ellenére, hogy var
local
– outerFunc
, innerFunc
továbbra is képes elolvasni és megváltoztatni az értékét.
#!/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}]"
Kimenet:
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:]
Q : Ez egy hiba a héjában (bash 4.3.42, Ubuntu 16.04, 64bit), vagy a várható viselkedés?
SZERKESZTÉS: Megoldva. Amint azt a @MarkPlotnick megjegyezte, ez valóban a várható viselkedés.
Megjegyzések
Válasz
A héjváltozók dinamikus hatókör . Ha egy változót lokalizálnak egy függvényhez, akkor ez a hatókör addig marad, amíg a függvény vissza nem tér, beleértve más függvények hívása során sem.
Két kivétel van:
-
a ksh93-ban, ha egy függvényt a szokásos
function_name () { … }
szintaxissal definiálunk, akkor a helyi változói engedelmeskednek a dinamikus hatókörnek. De ha egy függvényt a ksh szintaxissal határozunk meg:function function_name { … }
, akkor a helyi változó engedelmeskedik a lexikális / statikus hatókörnek, tehát nem láthatók más, ezzel meghívott függvényekben. -
a
zsh/private
automatikusan letölthető plugin azsh
fájlban egyprivate
keyword / builtin, amellyel statikus hatókörű változó deklarálható.
ash, bash, pdksh és származékai, a bosh csak dinamikus hatókörrel rendelkezik.
Megjegyzések
- A héjban lévő összes változónak van-e dinamikus hatóköre, vagy ez csak a
local
dátummal deklarált változókra vonatkozik? - @HaroldFischer Minden változó dinamikus hatókörrel rendelkezik.
typeset
vagydeclare
vagylocal
deklarációval a hatókör addig tart, amíg a függvény vissza nem tér. Ilyen nyilatkozat nélkül a hatókör globális. - IMHO,
If a variable is declared as local to a function, that scope remains until the function returns.
nem elegendő annak megmagyarázására, hogy mi a dinamikus hatókör verus lexikális hatókör. Önmagában a leírás a lexikális hatókörre is vonatkozik. - @jinbeomhong Nem, lexikális hatókör esetén a függvény változója nem látható, míg ez a függvény másik függvényt hív. ' Hozzáadtam egy mondatot, hogy ezt kifejezetten kimondjam.
- Ez befolyásolja a beépítetteket hívó függvényeket is? Vagy a beépített verzióknak megvan a saját hatókörük?
Válasz
Ez nem hiba, a kontextuson belüli hívás A externalFunc a $ var helyi másolatát használja. A “local” az externalFunc-ban azt jelenti, hogy a globális nem változik. Ha a innerFunc-ot az externalFunc-en kívül hívja meg, akkor a globális $ var megváltozik, de a externalFunc helyi $ var-ja nem. Ha a “local” értéket adta hozzá a belsőFunc-hoz, akkor a externalFunc “s $ var-ját nem változtatja meg – lényegében három lehet:
- $ global :: var
- $ externalFunc :: var
- $ innerFunc :: var
a Perl névtér formátumának használatához, egyfajta.
Válasz
A function innerFunc()
mezőben a var="new value"
-t nem deklarálták helyi ként, ezért látható hatókörben (egyszer) a függvényt meghívták).
Ezzel szemben a function outerFunc()
fájlban a local var="initial value"
helyi , ezért a globális hatókörben nem érhető el (még akkor sem, ha a függvényt meghívták).
Mivel a innerFunc()
-t a outerFunc()
, a var a outerFunc()
helyi hatókörébe tartozik.
man 1 bash
segíthet tisztázni
helyi [opció] [név [= érték] …]
Minden argumentumhoz egy helyi név névvel változó jön létre és hozzárendelt értéket kap. Az opció bármelyik lehet, amelyet a deklaráció fogad el.Ha a lokális funkciót egy függvényen belül használjuk, akkor a változó neve látható hatókörrel rendelkezik, amely az adott függvényre és gyermekeire korlátozódik. …
A leírásban elvárt implicit viselkedés a local var="new value
deklarálásával érhető el function innerFunc()
.
Ahogy mások is kijelentették, ez nem egy hiba a bash shellben. Minden úgy működik, ahogy kell.
Megjegyzések
- Az első állításod ellentmond a felhasználó által látottaknak. A
var
értékének globális hatókörben történő kinyomtatása után, miutáninnerFunc
meghívta a következőt:outFunc
, nem nyomtatnew value
.
Válasz
Használhat függvény a helyi hatókör kényszerítésére:
sh_local() { eval "$(set)" command eval "\"\$@\"" }
Példa:
x() { z="new value" printf "function x, z = [%s]\n" "$z" } y() { z="initial value" printf "function y before x, z = [%s]\n" "$z" sh_local x printf "function y after x, z = [%s]\n" "$z" } printf "global before y, z = [%s]\n" "$z" y printf "global after y, z = [%s]\n" "$z"
Eredmény:
global before y, z = [] function y before x, z = [initial value] function x, z = [new value] function y after x, z = [initial value] global after y, z = [initial value]
var
értéke üres? Avar
globálisan ainnerFunc
mezőben van beállítva, akkor miért nem ' áll fenn a végéig a szkriptet?