Après avoir lu 24.2. Variables locales , je pensais que déclarer une variable var
avec le mot-clé local
signifiait que sa var
valeur n'était accessible que dans le bloc de code délimité par les accolades d'une fonction.
Cependant, après l' exécution de l'exemple suivant, j'ai découvert que var
peut également être consulté, lu et écrit des fonctions invoquées par ce bloc de code - à savoir même si var
est déclarée local
à outerFunc
, innerFunc
est encore capable de le lire et de modifier sa valeur.
#!/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}]"
Sortie:
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: Est-ce un bug dans mon shell (bash 4.3.42, Ubuntu 16.04, 64bit) ou est-ce le comportement attendu?
EDIT: Résolu. Comme l'a noté @MarkPlotnick, c'est en effet le comportement attendu.
var
soit vide?var
est défini globalementinnerFunc
, alors pourquoi ne reste-t-il pas jusqu'à la fin du script?Réponses:
Les variables shell ont une portée dynamique . Si une variable est déclarée comme locale pour une fonction, cette étendue reste jusqu'à ce que la fonction retourne.
Il existe deux exceptions:
dans ksh93, si une fonction est définie avec la
function_name () { … }
syntaxe standard , ses variables locales obéissent à la portée dynamique. Mais si une fonction est définie avec la syntaxe ksh,function function_name { … }
alors sa variable locale obéit à la portée lexicale / statique, de sorte qu'elles ne sont pas visibles dans les autres fonctions appelées par cela.le
zsh/private
plugin autochargeablezsh
fournit unprivate
mot-clé / intégré qui peut être utilisé pour déclarer une variable à portée statique.frêne, bash, pdksh et dérivés, bosh n'a qu'une portée dynamique.
la source
local
?typeset
oudeclare
oulocal
, la portée est jusqu'à ce que la fonction retourne. Sans une telle déclaration, la portée est globale.Ce n'est pas un bug, l'appel dans le contexte de externalFunc utilise cette copie locale de $ var. Le "local" dans externalFunc signifie que le global n'est pas modifié. Si vous appelez innerFunc en dehors de externalFunc, alors il y aura un changement au $ var global, mais pas au $ var local du externalFunc. Si vous avez ajouté "local" à innerFunc, alors $ var de externalFunc ne serait pas modifié - en substance, il y en aurait 3:
pour utiliser le format d'espace de noms de Perl, en quelque sorte.
la source
Vous pouvez utiliser une fonction pour forcer la portée locale:
Exemple:
Résultat:
La source
la source
Dans
function innerFunc()
levar='new value'
n'a pas été déclaré comme local , il est donc disponible dans la portée visible (une fois que la fonction a été appelée).Inversement, dans
function outerFunc()
le alocal var='initial value'
été déclaré local , il n'est donc pas disponible dans la portée globale (même si la fonction a été appelée).Parce qu'il a
innerFunc()
été appelé en tant qu'enfant deouterFunc()
, var est dans la portée locale deouterFunc()
.man 1 bash
peut aider à clarifierLe comportement implicite attendu dans la description peut être obtenu en déclarant
local var='new value
dansfunction innerFunc()
.Comme d'autres l'ont dit, ce n'est pas un bogue dans le shell bash. Tout fonctionne comme il se doit.
la source
var
dans la portée globale, après avoir appelé àinnerFunc
traversoutFunc
, n'imprime pasnew value
.