Like "real" programming languages,
bash has functions, though in a
somewhat limited implementation. A function is a subroutine,
a code block that implements a set of operations, a "black
box" that performs a specified task. Whenever there is
repetitive code, when a task repeats with only slight variations,
then writing a function should be investigated.
function function-name {
command...
}
or
function-name () {
command...
}
This second form will cheer the hearts of C programmers.
The opening bracket in the function may optionally be placed on the
second line, to more nearly resemble C function syntax.
function-name ()
{
command...
}
Functions are called, triggered, simply by
invoking their names.
Note that the function definition must precede the first
call to it. There is no method of "declaring"
the function, as, for example, in C.
Example 3-80. Simple function
#!/bin/bash
funky ()
{
echo This is a funky function.
echo Now exiting funky function.
}
# Note: function must precede call.
# Now, call the function.
funky
exit 0 |
More complex functions may have arguments passed to them
and return exit values to the script for further
processing.
function-name $arg1 $arg2 |
The function refers to the passed arguments by position (as if they were
positional parameters), that is, $1,
$2, and so forth.
Example 3-81. Function Taking Parameters
#!/bin/bash
func2 () {
if [ -z $1 ]
# Checks if any params.
then
echo "No parameters passed to function."
return 0
else
echo "Param #1 is $1."
fi
if [ $2 ]
then
echo "Parameter #2 is $2."
fi
}
func2
# Called with no params
echo
func2 first
# Called with one param
echo
func2 first second
# Called with two params
echo
exit 0 |
Note: In contrast to certain other programming languages,
shell scripts permit passing only value parameters to functions.
Variable names (which are actually pointers), if passed as
parameters to functions, will be treated as string literals
and cannot be dereferenced. Functions interpret their
arguments literally.
- exit status
Functions return a value, called an exit
status. The exit status may be explicitly
specified by a return statement,
otherwise it is the exit status of the last command in
the function (0 if successful,
and a non-zero error code if not). This exit status
may be used in the script by referencing it as
$?.
- return
Terminates a function. The return statement
optionally takes an integer argument, which is returned to
the calling script as the "exit status" of the
function, and this exit status is assigned to the variable
$?.
Example 3-82. Converting numbers to Roman numerals
#!/bin/bash
# Arabic number to Roman numeral conversion
# Range 0 - 200
# It's crude, but it works.
# Extending the range and otherwise improving the script
# is left as an exercise for the reader.
# Usage: roman number-to-convert
ARG_ERR=1
OUT_OF_RANGE=200
if [ -z $1 ]
then
echo "Usage: `basename $0` number-to-convert"
exit $ARG_ERR
fi
num=$1
if [ $num -gt $OUT_OF_RANGE ]
then
echo "Out of range!"
exit $OUT_OF_RANGE
fi
to_roman ()
{
number=$1
factor=$2
rchar=$3
let "remainder = number - factor"
while [ $remainder -ge 0 ]
do
echo -n $rchar
let "number -= factor"
let "remainder = number - factor"
done
return $number
}
# Note: must declare function
# before first call to it.
to_roman $num 100 C
num=$?
to_roman $num 90 LXXXX
num=$?
to_roman $num 50 L
num=$?
to_roman $num 40 XL
num=$?
to_roman $num 10 X
num=$?
to_roman $num 9 IX
num=$?
to_roman $num 5 V
num=$?
to_roman $num 4 IV
num=$?
to_roman $num 1 I
echo
exit 0 |
- local variables
A variable declared as local is one
that is visible only within the block of code in which it
appears. In a shell script, this means the variable has
meaning only within its own function.
Example 3-83. Local variable visibility
#!/bin/bash
func ()
{
local a=23
echo
echo "a in function is $a"
echo
}
func
# Now, see if local 'a'
# exists outside function.
echo "a outside function is $a"
echo
# Nope, 'a' not visible globally.
exit 0 |
Local variables permit recursion (a recursive function
is one that calls itself), but this practice usually
involves much computational overhead and is definitely
not recommended in a shell
script.
Example 3-84. 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
WRONG_ARGS=1
RANGE_ERR=2
if [ -z $1 ]
then
echo "Usage: `basename $0` number"
exit $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 $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
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 |