Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting | ||
---|---|---|
Prev | Chapter 24. Functions | Next |
A variable declared as local is one that is visible only within the block of code in which it appears. It has local scope. In a function, a local variable has meaning only within that function block. [1]
Example 24-12. Local variable visibility
1 #!/bin/bash 2 # ex62.sh: Global and local variables inside a function. 3 4 func () 5 { 6 local loc_var=23 # Declared as local variable. 7 echo # Uses the 'local' builtin. 8 echo "\"loc_var\" in function = $loc_var" 9 global_var=999 # Not declared as local. 10 # Therefore, defaults to global. 11 echo "\"global_var\" in function = $global_var" 12 } 13 14 func 15 16 # Now, to see if local variable "loc_var" exists outside the function. 17 18 echo 19 echo "\"loc_var\" outside function = $loc_var" 20 # $loc_var outside function = 21 # No, $loc_var not visible globally. 22 echo "\"global_var\" outside function = $global_var" 23 # $global_var outside function = 999 24 # $global_var is visible globally. 25 echo 26 27 exit 0 28 # In contrast to C, a Bash variable declared inside a function 29 #+ is local ONLY if declared as such. |
Before a function is called, all variables declared within the function are invisible outside the body of the function, not just those explicitly declared as local.
|
As Evgeniy Ivanov points out, when declaring and setting a local variable in a single command, apparently the order of operations is to first set the variable, and only afterwards restrict it to local scope. This is reflected in the return value.
|
Recursion is an interesting and sometimes useful form of self-reference. Herbert Mayer defines it as ". . . expressing an algorithm by using a simpler version of that same algorithm . . ." Consider a definition defined in terms of itself, [2] an expression implicit in its own expression, [3] a snake swallowing its own tail, [4] or . . . a function that calls itself. [5] Example 24-13. Demonstration of a simple recursive function
Example 24-14. Another simple demonstration
|
Local variables are a useful tool for writing recursive code, but this practice generally involves a great deal of computational overhead and is definitely not recommended in a shell script. [6]
Example 24-15. Recursion, using a local variable
1 #!/bin/bash 2 3 # factorial 4 # --------- 5 6 7 # Does bash permit recursion? 8 # Well, yes, but... 9 # It's so slow that you gotta have rocks in your head to try it. 10 11 12 MAX_ARG=5 13 E_WRONG_ARGS=85 14 E_RANGE_ERR=86 15 16 17 if [ -z "$1" ] 18 then 19 echo "Usage: `basename $0` number" 20 exit $E_WRONG_ARGS 21 fi 22 23 if [ "$1" -gt $MAX_ARG ] 24 then 25 echo "Out of range ($MAX_ARG is maximum)." 26 # Let's get real now. 27 # If you want greater range than this, 28 #+ rewrite it in a Real Programming Language. 29 exit $E_RANGE_ERR 30 fi 31 32 fact () 33 { 34 local number=$1 35 # Variable "number" must be declared as local, 36 #+ otherwise this doesn't work. 37 if [ "$number" -eq 0 ] 38 then 39 factorial=1 # Factorial of 0 = 1. 40 else 41 let "decrnum = number - 1" 42 fact $decrnum # Recursive function call (the function calls itself). 43 let "factorial = $number * $?" 44 fi 45 46 return $factorial 47 } 48 49 fact $1 50 echo "Factorial of $1 is $?." 51 52 exit 0 |
Also see Example A-15 for an example of recursion in a script. Be aware that recursion is resource-intensive and executes slowly, and is therefore generally not appropriate in a script.
[1] | However, as Thomas Braunberger points out, a local variable declared in a function is also visible to functions called by the parent function.
This is documented in the Bash manual: "Local can only be used within a function; it makes the variable name have a visible scope restricted to that function and its children." [emphasis added] The ABS Guide author considers this behavior to be a bug. | |
[2] | Otherwise known as redundancy. | |
[3] | Otherwise known as tautology. | |
[4] | Otherwise known as a metaphor. | |
[5] | Otherwise known as a recursive function. | |
[6] | Too many levels of recursion may crash a script with a segfault.
|