My previous article on “Understanding and Writing functions in Shell Scripts” might have given you a basic idea on how to write functions under shell scripts. Now it is time to get deeper into functional features like the usage of local variables and recursion.
Local Variables
What makes a variable local? It depends on that particular block where the variable is declared. A variable declared as local will be accessible from that block of code where it appears i.e. its scope is local. In order to explain this thing let’s look into one example below.
#!/bin/bash func( ) { local i=10 j=20 echo "i from func = $i" echo "j from func = $j" } echo "i outside func = $i" echo "j outside func = $j" func echo "i outside func = $i" echo "j outside func = $j" exit 0
On executing the above script the output will be.
i outside func = j outside func = i from func = 10 j from func = 20 i outside func = j outside func = 20
This is because the function func has not yet called while the first 2 echo statements were executed. After calling the function func the same 2 echo statements produce a different result. Now the variable j, which was declared inside func and not local, could be accessed afterwards.
Thus value for j becomes 20. What about the local variable i? Since its scope was inside the function func, value 10 could not be accessed from outside. Note that the variable j normally declared inside func is global by default.
Now you are familiar with local variables and how to use them inside function blocks. Let us move on to the most interesting section under functions, the recursion.
What is Recursion?
A function calling itself is generally termed as the recursion procedure. Or it can be defined as expressing an algorithm by using a simpler version of that same algorithm. Consider the example of finding factorial of a number. We know that n! = 1 x 2 x 3 x … x (n-1) x n. Thus we can write a recurrence relation as:
n! = (n-1)! x n
So its easy for us to recursively call the same function and use the return value from each call to multiply with the previous result, i.e.
5! = 4! x 5 4! = 3! x 4 3! = 2! x 3 2! = 1! x 2 1! = 0! x 1
Recursion using Local Variables
Here we try to write a script for finding factorial of a number using local variables and recursion.
#!/bin/bash fact( ) { local num=$1 if [ $num -eq 0 ]; then ret=1 else temp=$((num-1)) fact $temp ret=$((num*$?)) fi return $ret } fact 5 echo "Factorial of 5 = $?" exit 0
num is a local variable used to store each n-1 value on each call. Here the base condition checks whether the number is equal to zero or not (since 0! = 1 and factorial is not defined for negative numbers). On arriving this base condition it returns the value 1 to its caller. Now num = 1 and ret = 1 x 1.
At this instant it returns 1 to its caller. Now num = 2 and ret = 2 x 1 and so on. Finally when num = 5 return value will be 24 and final result is ret = 5 x 24. The final result 120 is passed down to the initial caller statement and is displayed.
There is one problem in the above script. As I explained in the previous article, functions cannot return large integers. So its left to users to find a solution for the above issue.
Q. Can we perform recursion without using local variables? Answer is Yes.
Recursion without Local Variables
Look at the following example for displaying the Fibonacci series using recursion. The basic recurrence relation is:
fib(0) = 0 fib(1) = 1 else fib(n) = fib(n-1) + fib(n-2) Fibonacci series using recursion #!/bin/bash fib( ) { a=$1 if [ $a -lt 2 ]; then echo $a else ((--a)) b=$(fib $a) ((--a)) c=$(fib $a) echo $((b+c)) fi } for i in $(seq 0 15) do out=$(fib $i) echo $out done exit 0
No local variables are used in the above script. I hope you can understand the flow of script during execution.
Here the value 15 represents the number of terms in the Fibonacci series to be displayed. Did you notice anything special regarding the execution of above script. It takes a while, doesn’t it? Recursion in a script is slower than a recursion in programming languages like C.
With this article, I plan to conclude the functions part in shell scripting. Stay updated with Tecmint to have the upcoming articles on arrays and much more…
Try to understand the difference based on the output of following shell script:
#!/bin/bash
function return_func () {
echo “I’m returning, but not exiting . . .”
return 1
echo “This will not be displayed :-)”
}
function exit_func () {
echo “I’m exiting . . .”
exit 0
echo “This will not be displayed :-)”
}
echo
echo “Before returning.”
echo
return_func
if [ $? -eq 1 ]; then
echo
echo “Before exiting.”
echo
exit_func
fi
echo
echo “And you will not see this on execution”
exit 2
Check the output status using $? immediately after the execution of the above script. I hope that’s clear.
what is the difference between a return statement and an exit statement in shell functions.
Could you explain with some brief examples.