23.2. Local Variables and Recursion

Local variables make recursion possible.

local variables

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.

Example 23-8. Local variable visibility

#!/bin/bash

func ()
{
  local a=23
  echo
  echo "a in function = $a"
  echo
}  

func

# Now, see if local 'a' exists outside function.

echo "a outside function = $a"  # Nope, 'a' not visible globally.
echo

exit 0

Local variables permit recursion, [1] but this practice generally involves much computational overhead and is definitely not recommended in a shell script. [2]

Example 23-9. Recursion, using a local variable

#!/bin/bash

#               factorial
#               ---------


# Does bash permit recursion?
# Well, yes, but...
# You gotta have rocks in your head to try it.


MAX_ARG=5
E_WRONG_ARGS=65
E_RANGE_ERR=66


if [ -z "$1" ]
then
  echo "Usage: `basename $0` number"
  exit $E_WRONG_ARGS
fi

if [ "$1" -gt $MAX_ARG ]
then
  echo "Out of range (5 is maximum)."
  # Let's get real now.
  # If you want greater range than this,
  # rewrite it in a real programming language.
  exit $E_RANGE_ERR
fi  

fact ()
{
  local number=$1
  # Variable "number" must be declared as local,
  # otherwise this doesn't work.
  if [ "$number" -eq 0 ]
  then
    factorial=1    # Factorial of 0 = 1.
  else
    let "decrnum = number - 1"
    fact $decrnum  # Recursive function call.
    let "factorial = $number * $?"
  fi

  return $factorial
}

fact $1
echo "Factorial of $1 is $?."

exit 0

See also Example A-11 for an example of recursion in a script. Be aware that recursion is resource-intensive and executes slowly, and is therefore generally not appropriate to use in a script.

Notes

[1]

Herbert Mayer defines recursion as "...expressing an algorithm by using a simpler version of that same algorithm..." A recursive function is one that calls itself.

[2]

Too many levels of recursion may crash a script with a segfault.
#!/bin/bash

recursive_function ()		   
{
(( $1 < $2 )) && f $(( $1 + 1 )) $2;
#  As long as 1st parameter is less than 2nd,
#+ increment 1st and recurse.
}

recursive_function 1 50000  # Recurse 50,000 levels!
# Segfaults, of course.

#  Recursion this deep might cause even a C program to segfault,
#+ by using up all the memory allotted to the stack.

# Thanks, S.C.

exit 0  # This script will not exit normally.