Luettuasi 24.2. Paikalliset muuttujat , ajattelin, että muuttujan var
ilmoittaminen avainsanalla local
tarkoitti sitä, että var
”: n arvo oli käytettävissä vain koodilohkossa, jonka rajaavat funktion kiharat aaltosulkeet.
Seuraavan esimerkin suorittamisen jälkeen sain kuitenkin selville, että var
voidaan käyttää, lukea ja kirjoittaa myös toiminnoista, joihin kyseinen koodilohko on kutsunut – vaikka var
on ilmoitettu local
– outerFunc
, innerFunc
pystyy edelleen lukemaan sen ja muuttamaan sen arvoa.
#!/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}]"
Tulos:
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 : Onko se vika kuoressani (bash 4.3.42, Ubuntu 16.04, 64bit) vai onko se odotettua käyttäytymistä?
MUOKKAA: Ratkaistu. Kuten @MarkPlotnick huomautti, tämä on todellakin odotettua käyttäytymistä.
Kommentit
vastaus
Shell-muuttujilla on dynaaminen laajuus . Jos muuttuja ilmoitetaan paikalliseksi funktiolle, kyseinen laajuus pysyy, kunnes funktio palaa, mukaan lukien muihin toimintoihin soitettujen puheluiden aikana.
On olemassa kaksi poikkeusta:
-
ksh93: ssä, jos funktio määritetään vakiosyntaksilla
function_name () { … }
, sen paikalliset muuttujat noudattavat dynaamista laajuutta. Mutta jos funktio määritetään ksh-syntaksillafunction function_name { … }
, sen paikallinen muuttuja noudattaa leksikaalista / staattista ulottuvuutta, joten ne eivät ole näkyvissä muissa tällä kutsumissa funktioissa. -
zsh/private
automaattisesti ladattava laajennuszsh
sisältääprivate
avainsana / sisäänrakennettu, jota voidaan käyttää staattisen laajuuden muuttujan ilmoittamiseen.
ash, bash, pdksh ja johdannaiset, boshilla on vain dynaaminen ulottuvuus.
Kommentit
- Onko kaikilla kuoren muuttujilla dynaaminen laajuus vai koskeeko tämä vain muuttujia, jotka on ilmoitettu merkinnällä
local
? - @HaroldFischer Kaikilla muuttujilla on dynaaminen laajuus.
typeset
– taideclare
– tailocal
-lausekkeen kanssa soveltamisala on, kunnes funktio palaa. Ilman tällaista ilmoitusta soveltamisala on globaali. - IMHO,
If a variable is declared as local to a function, that scope remains until the function returns.
ei riitä selittämään, mikä on dynaaminen laajuus verus leksikaalinen. Pelkästään kuvausta sovelletaan myös leksikaaliseen laajuuteen. - @jinbeomhong Ei, leksikaalisen laajuuden mukaan funktion muuttuja ei ole näkyvissä, kun taas tämä funktio kutsuu toista toimintoa. Olen ' lisännyt lauseen ilmaisemaan tämän nimenomaisesti.
- Vaikuttaako tämä myös sisäänrakennuksia kutsuviin funktioihin? Vai onko sisäänrakennetuilla laitteilla oma soveltamisala?
Vastaa
Se ei ole virhe, puhelu kontekstissa of externalFunc käyttää sitä $ var: n paikallista kopiota. ”local” osiossa externalFunc tarkoittaa, että globaalia ei muuteta. Jos kutsut sisäistä funktiota ulkoisen funktion ulkopuolelle, muutos globaaliin $ var: iin tapahtuu, mutta ei ulkoisenFunc: n paikalliseen $ variin. Jos lisääit ”local”: n sisäiseen funktioon, ulkoisen funktion ”s $ var” ei muutu – Pohjimmiltaan heitä on 3:
- $ global :: var
- $ externalFunc :: var
- $ innerFunc :: var
käyttää Perlin nimiavaruusmuotoa, eräänlainen.
Vastaa
Kohdassa function innerFunc()
var="new value"
ei ilmoitettu paikalliseksi , joten se on käytettävissä näkyvissä (kerran toimintoa on kutsuttu).
Käänteisesti function outerFunc()
-kohdassa local var="initial value"
julistettiin paikalliseksi , joten se ei ole käytettävissä maailmanlaajuisesti (vaikka toimintoa olisi kutsuttu).
Koska innerFunc()
kutsuttiin outerFunc()
, var on outerFunc()
-alueen laajuudessa.
man 1 bash
voi auttaa selventämään
paikallinen [vaihtoehto] [nimi [= arvo] …]
Jokaiselle argumentille paikallinen muuttuja nimeltä nimi luodaan ja määritetään arvo. Vaihtoehto voi olla mikä tahansa julistuksen hyväksymästä vaihtoehdosta.Kun funktiossa käytetään paikallista, se saa muuttujan nimen näkyväksi vain funktiolle ja sen lapsille. …
Epäsuora käyttäytyminen, jonka kuvauksessa odotetaan, voidaan saavuttaa ilmoittamalla local var="new value
function innerFunc()
.
Kuten muut ovat todenneet, tämä ei ole vika bash-kuoressa. Kaikki toimii kuten pitäisi.
Kommentit
- Ensimmäinen lauseesi on ristiriidassa käyttäjän näkemien asioiden kanssa.
var
-arvon tulostaminen globaalissa laajuudessa, kuninnerFunc
on kutsuttuoutFunc
-palvelun kautta ei tulostanew value
.
Vastaa
Voit käyttää toiminto pakottaa paikallinen laajuus:
sh_local() { eval "$(set)" command eval "\"\$@\"" }
Esimerkki:
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"
Tulos:
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
arvo on tyhjä?var
on asetettu globaalisti kohtaaninnerFunc
, joten miksi ' ei se tartu loppuun asti komentosarjan?