Une fonction peut s'appeller récursivement sans même utiliser de variables locales.
Exemple 23.15. La séquence de Fibonacci
#!/bin/bash
# fibo.sh : Fibonacci sequence (recursive)
# Author: M. Cooper
# License: GPL3
# ---------------------------------
# Fibo(0) = 0
# Fibo(1) = 1
# else
# Fibo(j) = Fibo(j-1) + Fibo(j-2)
# ---------------------------------
MAXTERM=15 # Number of terms (+1) to generate.
MINIDX=2 # If idx is less than 2, then Fibo(idx) = idx.
Fibonacci ()
{
idx=$1 # Doesn't need to be local. Why not?
if [ "$idx" -lt "$MINIDX" ]
then
echo "$idx" # First two terms are 0 1 ... see above.
else
(( --idx )) # j-1
term1=$( Fibonacci $idx ) # Fibo(j-1)
(( --idx )) # j-2
term2=$( Fibonacci $idx ) # Fibo(j-2)
echo $(( term1 + term2 ))
fi
# An ugly, ugly kludge.
# The more elegant implementation of recursive fibo in C
#+ is a straightforward translation of the algorithm in lines 7 - 10.
}
for i in $(seq 0 $MAXTERM)
do # Calculate $MAXTERM+1 terms.
FIBO=$(Fibonacci $i)
echo -n "$FIBO "
done
# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
# Takes a while, doesn't it? Recursion in a script is slow.
echo
exit 0
Exemple 23.16. Les tours d'Hanoi
#! /bin/bash
#
# La tour d'Hanoi
# Script bash
# Copyright (C) 2000 Amit Singh. All Rights Reserved.
# http://hanoi.kernelthread.com
#
# Testé avec bash version 2.05b.0(13)-release
# Fonctionne aussi avec Bash version 3.x.
#
# Utilisé dans le "Guide d'écriture avancé des scripts Bash"
#+ Avec l'autorisation de l'auteur du script.
# Légèrement modifié et commenté par l'auteur d'ABS.
#=================================================================#
# La tour d'Hanoi est un puzzle mathématique attribué à Édouard Lucas,
#+ un mathématicien français du 19è siècle.
# Il y a un ensemble de trois positions verticales dans une base.
# Le premier poste dispose d'un ensemble d'anneaux empilés.
# Les anneaux sont des disques plats avec un trou en leur centre,
#+ de manière à être placés sur les batons.
# Les anneaux ont des diamètres différents et ils s'assemblent en ordre
#+ descendant suivant leur taille.
# La plus petite est au-dessus et la plus large à la base.
#
# Le problème consiste à transférer la pile d'anneaux d'un baton à un autre.
# Vous pouvez bouger seulement un anneau à la fois.
# Il vous est permis de replacer les anneaux à leur baton d'origine.
# Vous pouvez placer un petit anneau sur un plus gros mais pas le contraire.
# Encore une fois, il est interdit de placer un gros anneau sur un plus petit.
#
# Pour un petit nombre d'anneaux, seuls quelques mouvements sont nécessaires.
#+ Pour chaque anneau supplémentaire, le nombre de déplacements requis double
#+ approximativement et la "stratégie" devient de plus en plus complexe.
#
# Pour plus d'informations, voir http://hanoi.kernelthread.com
#+ ou pp. 186-92 de _The Armchair Universe_ par A.K. Dewdney.
#
#
# ... ... ...
# | | | | | |
# _|_|_ | | | |
# |_____| | | | |
# |_______| | | | |
# |_________| | | | |
# |___________| | | | |
# | | | | | |
# .--------------------------------------------------------------.
# |**************************************************************|
# #1 #2 #3
#
#=================================================================#
E_SANSPARAM=66 # Aucun paramètre passé au script.
E_MAUVAISPARAM=67 # Nombre illégal de disques.
Deplacements= # Variable globale contenant le nombre de déplacements.
# Modification du script original.
fait_hanoi() { # Fonction récursive.
case $1 in
0)
;;
*)
fait_hanoi "$(($1-1))" $2 $4 $3
echo move $2 "-->" $3
((Deplacements++)) # Modification du script original.
fait_hanoi "$(($1-1))" $4 $3 $2
;;
esac
}
case $# in
1) case $(($1>0)) in # Il doit y avoir au moins un disque.
1) # Instruction case imbriquée.
fait_hanoi $1 1 3 2
echo "Nombre total de déplacements = $Deplacements"
exit 0;
;;
*)
echo "$0: valeur illégale pour le nombre de disques";
exit $E_MAUVAISPARAM;
;;
esac
;;
*)
echo "usage: $0 N"
echo " où \"N\" est le nombre de disques."
exit $E_SANSPARAM;
;;
esac
# Exercices:
# ---------
# 1) Est-ce que les commandes au delà de ce point seront exécutées ?
# Pourquoi ? (Facile)
# 2) Expliquer le fonctionnement de la fonction "fait_hanoi".
# (Difficile -- voir la référence sur Dewdney ci-dessus.)