Etter å ha lest 24.2. Lokale variabler , jeg tenkte at å erklære en variabel var
med nøkkelordet local
betydde at var
«s verdi var bare tilgjengelig i kodeblokken avgrenset av krøllbøylene til en funksjon.
Imidlertid, etter å ha kjørt følgende eksempel, fant jeg ut at var
kan også nås, leses og skrives fra funksjonene påkalt av kodeblokken – dvs. selv om var
blir erklært local
til outerFunc
, innerFunc
er fremdeles i stand til å lese den og endre verdien.
#!/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}]"
Utgang:
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 : Er det en feil i skallet mitt (bash 4.3.42, Ubuntu 16.04, 64bit) eller er det forventet oppførsel?
EDIT: Løst. Som bemerket av @MarkPlotnick, er dette virkelig den forventede atferden.
Kommentarer
Svar
Shell-variabler har en dynamisk omfang . Hvis en variabel blir erklært som lokal for en funksjon, forblir dette omfanget til funksjonen returnerer, inkludert under samtaler til andre funksjoner.
Det er to unntak:
-
i ksh93, hvis en funksjon er definert med standard
function_name () { … }
syntaksen, så følger de lokale variablene dynamisk omfang. Men hvis en funksjon er definert med ksh-syntaksenfunction function_name { … }
, følger den lokale variabelen leksikalsk / statisk avgrensning, så de er ikke synlige i andre funksjoner som kalles dette. li> -
zsh/private
autoladable plugin izsh
gir enprivate
nøkkelord / innebygd som kan brukes til å erklære en variabel med statisk omfang.
ask, bash, pdksh og derivater, bosh har bare dynamisk scoping.
Kommentarer
- Har alle variablene i skallet et dynamisk omfang, eller gjelder dette bare variabler erklært med
local
? - @HaroldFischer Alle variabler har dynamisk omfang. Med en
typeset
ellerdeclare
ellerlocal
-erklæring, er omfanget til funksjonen returnerer. Uten en slik erklæring er omfanget globalt. - IMHO,
If a variable is declared as local to a function, that scope remains until the function returns.
er ikke nok til å forklare hva som er dynamisk omfang i forhold til leksikalt omfang. Beskrivelsen alene blir også brukt på leksikalt omfang. - @jinbeomhong Nei, med leksikalt omfang er en variabel fra en funksjon ikke synlig mens denne funksjonen kaller en annen funksjon. Jeg ' har lagt til en setning for å uttrykke dette eksplisitt.
- Påvirker dette også funksjonskalling innebygde? Eller har innebygde sitt eget omfang?
Svar
Det er ikke «en feil, samtalen i konteksten av outerFunc bruker den lokale kopien av $ var. Den «lokale» i outerFunc betyr at det globale ikke er endret. Hvis du kaller innerFunc utenfor den ytre Func, vil det være en endring i den globale $ var, men ikke den ytre Funcs lokale $ var. Hvis du la til «lokal» til innerFunc, ville ikke ytre Func «s $ var ikke endret – i hovedsak ville det være tre av dem:
- $ global :: var
- $ outerFunc :: var
- $ innerFunc :: var
for å bruke Perls navneplassformat, liksom.
Svar
I function innerFunc()
ble var="new value"
ikke erklært som lokal , derfor er den tilgjengelig i synlig omfang (en gang funksjonen har blitt kalt).
Omvendt ble function outerFunc()
local var="initial value"
erklært som lokal , derfor er den ikke tilgjengelig i det globale omfanget (selv om funksjonen er blitt kalt).
Fordi innerFunc()
ble kalt som barn av outerFunc()
, var ligger innenfor det lokale omfanget av outerFunc()
.
man 1 bash
kan bidra til å avklare
local [option] [name [= value] …]
For hvert argument, et lokalt variabel med navn blir opprettet og tildelt verdi. Alternativet kan være hvilket som helst av alternativene som godtas av erklær.Når lokalt brukes i en funksjon, fører det til at variabelnavnet har et synlig omfang begrenset til den funksjonen og dens barn. …
Den underforståtte oppførselen som forventes i beskrivelsen kan oppnås ved å erklære local var="new value
i function innerFunc()
.
Som andre har uttalt, er dette ikke en feil i bash-skallet. Alt fungerer som det skal.
Kommentarer
- Din første uttalelse strider mot det brukeren ser. Hvis du skriver ut verdien av
var
i det globale omfanget, etter å ha ringtinnerFunc
gjennomoutFunc
, gjør ikke skriv utnew value
.
Svar
Du kan bruke en funksjon for å tvinge lokalt omfang:
sh_local() { eval "$(set)" command eval "\"\$@\"" }
Eksempel:
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"
Resultat:
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
på den siste utgangslinjen er tom?var
er satt globalt iinnerFunc
, så hvorfor holder det ikke ' til slutten av skriptet?