A helyi változók hatóköre a héjfüggvényekben

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 localouterFunc, innerFunc továbbra is képes elolvasni és megváltoztatni az értékét.

Online futtatás

#!/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

  • Ez a várható viselkedés
  • Vagyok az egyetlen, aki szerint ' furcsa, hogy a kimenet utolsó sorában a var értéke üres? A var globálisan a innerFunc mezőben van beállítva, akkor miért nem ' áll fenn a végéig a szkriptet?

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:

  1. 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.

  2. a zsh/private automatikusan letölthető plugin a zsh fájlban egy private 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 vagy declare vagy local 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án innerFunc meghívta a következőt: outFunc, nem nyomtat new 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] 

Forrás

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük