diff --git a/shell_variables_scope.md b/shell_variables_scope.md new file mode 100644 index 00000000..aba9d163 --- /dev/null +++ b/shell_variables_scope.md @@ -0,0 +1,219 @@ +### General scope of variables + +Variables exists for the current shell and its children only. +Another script executed from the script is not a child, it's another shell which herited only the environment variables from its caller script, not its globals or locals variables. + +When a script is called, it isn't started in the current shell, but in a new instance of bash which herite environment variables from its parent. +```bash +var1=value1 +export var2=value2 + +echo "$var1" +echo "$var2" +# var1 and var2 exist + +echo "-" + +echo " +echo \"\$var1\" +echo \"\$var2\"" > other_script.sh +chmod +x other_script.sh +./other_script.sh +# Here, var1 doesn't exist, only var2 still exists. +# Because it's an environment variable. +``` +In your current shell, where you launch this script, try +```bash +echo $var1 - $var2 +``` +None of this 2 variables exists, because their scope is limited to the script itself. Never its parent. + + +### Functions inside a script + +Use a function would not change the scope of variables. +```bash +var1=value1 +export var2=value2 + +set_variable () { + var3=value3 + export var4=value4 + + echo "$var1" + echo "$var2" + echo "$var3" + echo "$var4" + # All variables exists here + # Because the function inherite its variables from the script. +} + +set_variable + +echo "$var1" +echo "$var2" +echo "$var3" +echo "$var4" +# var1 var2, var3 and var4 exist +# var3 exist because the function is executed in the same shell than the script itself. + +echo "-" + +echo " +echo \"\$var1\" +echo \"\$var2\" +echo \"\$var3\" +echo \"\$var4\"" > other_script.sh +chmod +x other_script.sh +./other_script.sh +# Here, var1 and var3 don't exist, only var2 and var4 still exist. +# Because they're environment variables. +``` + +### The usage of locales variables + +Locales variables are limited to the function and its children. +```bash +var1=value1 +export var2=value2 + +set_variable () { + var3=value3 + export var4=value4 + local var5=value5 + + echo "$var1" + echo "$var2" + echo "$var3" + echo "$var4" + echo "$var5" + # All variables exists here + # Because the function inherite its variables from the script. +} + +set_variable + +echo "-" + +echo "$var1" +echo "$var2" +echo "$var3" +echo "$var4" +echo "$var5" +# var1 var2, var3 and var4 exist +# var3 exist because the function is executed in the same shell than the script itself. +# var5 doesn't exist, because its scope is limited to the function which declare it. + +echo "-" + +echo " +echo \"\$var1\" +echo \"\$var2\" +echo \"\$var3\" +echo \"\$var4\" +echo \"\$var5\"" > other_script.sh +chmod +x other_script.sh +./other_script.sh +# Here, var1, var3 and var5 don't exist, only var2 and var4 still exist. +# Because they're environment variables. +``` + +Using a local variable is usefull for limit it scope to the function only. And not bother the script in its globality with useless variables. +But there's also another advantage with local variable, do not modify the content of a global variable. +```bash +var1=value1 +var2=value2 +var3=value3 + +set_variable () { + echo "$var1" + echo "$var2" + echo "$var3" + + echo "-" + + var2=new_value2 + local var3=new_value3 + + echo "$var1" + echo "$var2" + echo "$var3" + # Values of var2 and var3 are modified in the function. +} + +set_variable + +echo "-" + +echo "$var1" +echo "$var2" +echo "$var3" +# var3 retake is original value, +# because in the function, var3 was declared as a new locale variable. +# But var2 was directly modified, so its value still changed. +# Because, var2 in the function is still a global variable. +``` + +As seen previously, modified or created variables in a function can affect the main script because the function is executed in the same shell. +But, the things are different if the function is executed in a sub shell, the function become a child which only inherite from its parent. +```bash +var1=value1 +var2=value2 +var3=value3 + +fonction2 () { + echo "-" + echo "var1=$var1" + echo "var2=$var2" + echo "var3=$var3" + echo "var4=$var4" + echo "var5=$var5" + # Even var3, which is local, is inherited from the parent function. +} + +set_variable () { + echo "var1=$var1" + echo "var2=$var2" + echo "var3=$var3" + # Variables are inherited from the parent. + + echo "-" + + var2=new_value2 + local var3=new_value3 + var4=new_value4 + export var5=new_value5 + + echo "var1=$var1" + echo "var2=$var2" + echo "var3=$var3" + echo "var4=$var4" + echo "var5=$var5" + # Values of var2 and var3 are modified in the function. + + (fonction2) +} + +(set_variable) +# Start the function in a sub shell. + +echo "-" + +echo "var1=$var1" +echo "var2=$var2" +echo "var3=$var3" +echo "var4=$var4" +echo "var5=$var5" +# var2 and var3 retake their original values. +# Because the function is in a child shell which never affect its parent. +# Likewise, var4 and var5 don't exist, because they're been declared in child shell. +# The parent never inherite from its children shell. +``` + +### Conclusion + +- The scope of a variable is always the current shell and its children, never its parent shell. +- An environment variable may be exported to a new shell, detached from the first one. If the last one executed the second one. But, it can't affect the parents. +- A locale variable in a function, executed in the current shell, can't affect the environment outside of the function. End allow also to not affect a global variable with the same name. +- A function executed in a sub shell will never affect its parent, with global or local variables. +- A parent can NEVER be affected by variables defined or modified in its children shell. diff --git a/shell_variables_scope_fr.md b/shell_variables_scope_fr.md new file mode 100644 index 00000000..179f3252 --- /dev/null +++ b/shell_variables_scope_fr.md @@ -0,0 +1,219 @@ +### Portée générales des variables + +Les variables existent pour le shell courant et ses enfants uniquement. +Un script exécuté depuis le script n'est pas un enfant, c'est un autre shell qui n'héritera que des variables d'environnement du script appelant, pas des variables globales ou locales. + +Lors de l'appel d'un script, il n'est pas démarré dans le shell courant, mais dans une nouvelle instance de bash qui hérite des variables d'environnements de son parent. +```bash +var1=value1 +export var2=value2 + +echo "$var1" +echo "$var2" +# var1 et var2 existent + +echo "-" + +echo " +echo \"\$var1\" +echo \"\$var2\"" > other_script.sh +chmod +x other_script.sh +./other_script.sh +# Ici, var1 n'existe pas, seul var2 existe encore. +# Car c'est une variable d'environnement. +``` +Dans le shell courant, d'où le script est appelé, faite +```bash +echo $var1 - $var2 +``` +Aucune des 2 variables n'existent, car leur portée se limite au script appelé. Jamais au parent. + + +### Les fonctions dans un script + +Utiliser une fonction ne change pas la portée des variables. +```bash +var1=value1 +export var2=value2 + +set_variable () { + var3=value3 + export var4=value4 + + echo "$var1" + echo "$var2" + echo "$var3" + echo "$var4" + # Toutes les variables existent ici + # car la fonction hérite des variables du script. +} + +set_variable + +echo "$var1" +echo "$var2" +echo "$var3" +echo "$var4" +# var1 var2, var3 et var4 existent +# var3 existe car la fonction est exécutée dans le même shell que le script lui-même. + +echo "-" + +echo " +echo \"\$var1\" +echo \"\$var2\" +echo \"\$var3\" +echo \"\$var4\"" > other_script.sh +chmod +x other_script.sh +./other_script.sh +# Ici, var1 et var3 n'existent pas, seul var2 et var4 existe encore. +# Car ce sont des variables d'environnements. +``` + +### L'usage des variables locales + +Les variables locales sont limitées à une fonction et ses enfants +```bash +var1=value1 +export var2=value2 + +set_variable () { + var3=value3 + export var4=value4 + local var5=value5 + + echo "$var1" + echo "$var2" + echo "$var3" + echo "$var4" + echo "$var5" + # Toutes les variables existent ici + # car la fonction hérite des variables du script. +} + +set_variable + +echo "-" + +echo "$var1" +echo "$var2" +echo "$var3" +echo "$var4" +echo "$var5" +# var1 var2, var3 et var4 existent +# var3 existe car la fonction est exécutée dans le même shell que le script lui-même. +# var5 n'existe pas, car sa portée se limite à la fonction qui l'a déclaré + +echo "-" + +echo " +echo \"\$var1\" +echo \"\$var2\" +echo \"\$var3\" +echo \"\$var4\" +echo \"\$var5\"" > other_script.sh +chmod +x other_script.sh +./other_script.sh +# Ici, var1, var3 et var5 n'existent pas, seul var2 et var4 existe encore. +# Car ce sont des variables d'environnements. +``` + +L'intérêt d'utiliser une variable locale est donc de limiter cette variable à la seule fonction qui l'a déclaré. Et donc ne pas polluer le script dans sa globalité avec des variables inutile pour ce dernier. +Il existe également un second avantage à l'usage d'une variable locale, c'est de ne pas modifier le contenu d'une variable globale. +```bash +var1=value1 +var2=value2 +var3=value3 + +set_variable () { + echo "$var1" + echo "$var2" + echo "$var3" + + echo "-" + + var2=new_value2 + local var3=new_value3 + + echo "$var1" + echo "$var2" + echo "$var3" + # La valeurs de var2 et var3 sont modifiées dans la fonction +} + +set_variable + +echo "-" + +echo "$var1" +echo "$var2" +echo "$var3" +# var3 a repris sa valeur initiale, +# car dans la fonction var3 a été déclaré comme une nouvelle variable locale. +# Mais var2 a été modifiée directement, donc sa valeur reste modifiée. +# Car var2 dans la fonction est resté une variable globale. +``` + +Comme vu précédemment, les variables modifiée ou créée dans la fonction affecte le script car la fonction est exécutée dans le même shell que celui-ci. +Cela change si on exécute la fonction dans un sous-shell, la fonction devient un enfant qui hérite de son parent uniquement. +```bash +var1=value1 +var2=value2 +var3=value3 + +fonction2 () { + echo "-" + echo "var1=$var1" + echo "var2=$var2" + echo "var3=$var3" + echo "var4=$var4" + echo "var5=$var5" + # Même var3, qui est locale, est héritée par la fonction enfant. +} + +set_variable () { + echo "var1=$var1" + echo "var2=$var2" + echo "var3=$var3" + # Les variables sont héritées du parent. + + echo "-" + + var2=new_value2 + local var3=new_value3 + var4=new_value4 + export var5=new_value5 + + echo "var1=$var1" + echo "var2=$var2" + echo "var3=$var3" + echo "var4=$var4" + echo "var5=$var5" + # La valeurs de var2 et var3 sont modifiées dans la fonction + + (fonction2) +} + +(set_variable) +# Démarre la fonction dans un shell fils. + +echo "-" + +echo "var1=$var1" +echo "var2=$var2" +echo "var3=$var3" +echo "var4=$var4" +echo "var5=$var5" +# var2 et var3 ont repris leur valeurs initiales, +# Car la fonction est dans un shell enfant qui n'affecte pas son parent. +# De même, var4 et var5 n'existent pas, car elle sont déclarées dans un shell enfant. +# Le parent n'hérite pas des shells enfants. +``` + +### Conclusion + +- La portée d'une variable est toujours le shell courant et ses enfants, jamais son shell parent. +- Une variable d'environnement peut être exportée sur un nouveau shell, indépendant du premier. À condition que ce dernier exécute le second. Mais ne peut pas affecter les parents. +- Une variable locale dans une fonction, exécutée dans le shell courant, n'affecte pas son environnement en dehors de la fonction. Et permet également de ne pas affecter le contenu d'une variable globale de même nom. +- Une fonction exécutée dans un sous-shell n'affecte jamais le parent, que ses variables soient globales ou locales. +- Le parent n'est JAMAIS affecté par les variables définies ou modifiées par ses shells enfants.