Les fonctions permettent de regrouper et d'exécuter des commandes à différents endroits d'un script.
Cela permet de créer des fonctions personnalisées réutilisables.
Une fonction doit être définie au début d'un script, avant sa première utilisation.
Il existe 2 syntaxes permettant de définir une fonction.
Première syntaxe :
Ce sont les doubles parenthèses ( ) qui indique au shell la définition d'une fonction
Définition d'une fonction
maFonction () {
commande1
commande2
.....
}
Appel d'une fonction
maFonction
Seconde syntaxe :
Le mot clé function remplace les doubles parenthèses ( )
Définition d'une fonction
function maFonction {
commande1
commande2
.....
}
Appel d'une fonction
maFonction
Une fonction peut être appelée aussi bien à partir du programme principal qu'à partir d'une autre fonction.
Exemple :
$ nl fonction01.sh
1 #!/bin/bash
2 fctn01 () {
3 echo "Fonction fctn01"
4 }
5 function fctn02 {
6 echo "Fonction fctn02"
7 }
8 echo "Début du programme principal"
9 echo "Appel de la fonction fctn01"
10 fctn01
11 echo "Appel de la fonction fctn02"
12 fctn02
13 echo "Fin du programme principal"
14 exit 0
$ ./fonction01.sh
Début du programme principal
Appel de la fonction fctn01
Fonction fctn01
Appel de la fonction fctn02
Fonction fctn02
Fin du programme principal
$
Dès qu'une fonction est définie, celle-ci est considérée par le shell comme étant une commande interne.
Comme toutes commandes Linux, une fonction retourne également un code d'erreur.
Si le code erreur n'est pas spécifié, celui retourné par défaut correspond au code erreur de la dernière commande exécutée dans la fonction.
La commande return permet de retourner le code erreur de la fonction concernée. Ce code doit obligatoirement correspondre à un nombre compris entre 0 et 255.
Le code erreur retourné par la fonction est récupérable grâce à la variable $?.
Exemple :
Le script suivant test si l'utilisateur saisi existe sur le système.
$ nl fonction02.sh
1 #!/bin/bash
2 function pause {
3 echo "Appuyer sur Entrée pour continuer"
4 read x
5 }
6 function existUser {
7 echo -e "Saisir le nom d'un utilisateur : \c"
8 read user
9 if grep -q "^$user:" /etc/passwd ; then
10 return 0
11 fi
12 return 1
13 }
14 while true
15 do
16 clear
17 echo "- 1 - Savoir si un utilisateur existe"
18 echo "- 2 - Connaitre l'UID d'un utilisateur"
19 echo "- 3 - Fin"
20 echo -e "Votre choix : \c"
21 read choix
22 case $choix in
23 1) if existUser
24 then
25 echo "L'utilisateur $user existe"
26 else
27 echo "l'utilisateur $user n'existe pas"
28 fi
29 ;;
30 2) echo "Option non disponible"
31 ;;
32 3) exit 0
33 ;;
34 esac
35 pause
36 done
$
Dans un script shell, sans définition particulière, toutes les variables utilisées sont globales à tout le script.
Qu'une variable soit définie au niveau du programme principal ou d'une fonction, elle est accessible n'importe où dans le script.
Par exemple, dans le script fonction02.sh, la variable $user est initialisée dans la fonction existUser (ligne 8) et utilisée également au niveau du programme principal (ligne 25 et 27).
$ nl fonction02.sh
1 #!/bin/bash
2 function pause {
3 echo "Appuyer sur Entrée pour continuer"
4 read x
5 }
6 function existUser {
7 echo -e "Saisir le nom d'un utilisateur : \c"
8 read user
9 if grep -q "^$user:" /etc/passwd ; then
10 return 0
11 fi
12 return 1
13 }
14 while true
15 do
16 clear
17 echo "- 1 - Savoir si un utilisateur existe"
18 echo "- 2 - Connaitre l'UID d'un utilisateur"
19 echo "- 3 - Fin"
20 echo -e "Votre choix : \c"
21 read choix
22 case $choix in
23 1) if existUser
24 then
25 echo "L'utilisateur $user existe"
26 else
27 echo "l'utilisateur $user n'existe pas"
28 fi
29 ;;
30 2) echo "Option non disponible"
31 ;;
32 3) exit 0
33 ;;
34 esac
35 pause
36 done
$
La commande typeset permet de définir des variables locales à une fonction.
Syntaxe :
typeset variable
typeset variable=valeur
Exemple :
$ nl fonction03.sh
1 #!/bin/bash
2 function f1 {
3 # var1 est une variable locale
4 typeset var1
5 echo "Dans la fonction f1 => var1 avant : $var1"
6 var1=100
7 echo "Dans la fonction f1 => var1 après : $var1"
8 echo "Dans la fonction f1 => var2 avant : $var2"
9 var2=200
10 echo "Dans la fonction f1 => var2 après : $var2"
11 }
12 # var1 et var2 sont des variables globales
13 var1=1
14 var2=2
15 echo "Dans le programme principal => var1 avant appel f1 : $var1"
16 echo "Dans le programme principal => var2 avant appel f1 : $var2"
17 f1
18 echo "Dans le programme principal => var1 après appel f1 : $var1"
19 echo "Dans le programme principal => var2 après appel f1 : $var2"
20 exit 0
$ ./fonction03.sh
Dans le programme principal => var1 avant appel f1 : 1
Dans le programme principal => var2 avant appel f1 : 2
Dans la fonction f1 => var1 avant :
Dans la fonction f1 => var1 après : 100
Dans la fonction f1 => var2 avant : 2
Dans la fonction f1 => var2 après : 200
Dans le programme principal => var1 après appel f1 : 1
Dans le programme principal => var2 après appel f1 : 200
$
2 variables globales var1 et var2 sont définies et initialisées ligne 13 et 14.
1 variable locale var1 est définie dans la fonction ligne 4 et initialisée à 100 ligne 6.
Après exécution de la fonction f1, la variable globale var1 a conservée sa valeur (1) alors que la variable globale var2 a été modifiée.
Dans un script shell, il est tout à fait possible de passer des arguments à une fonction étant donné qu'une fonction est reconnue par le shell comme étant une commande à part entière.
Ces arguments sont récupérables dans les fonctions grâce aux variables spéciales $1, $2, $3, ....., ${10} ......$*, $@ et $#. Ces variables sont aussi locales aux fonctions.
Par contre, la variable $0 contient toujours le nom du script.
Exemple :
$ nl fonction04.sh
1 #!/bin/bash
2 function f1 {
3 echo "Arguments de la fonction f1 :"
4 echo "\$0 => $0"
5 echo "\$1 => $1"
6 echo "\$2 => $2"
7 echo "\$3 => $3"
8 echo "\$* => $*"
9 echo "\$# => $#"
10 }
11 function f2 {
12 echo "Arguments de la fonction f2 :"
13 echo "\$0 => $0"
14 echo "\$1 => $1"
15 echo "\$2 => $2"
16 echo "\$3 => $3"
17 echo "\$* => $*"
18 echo "\$# => $#"
19 }
20 function f3 {
21 echo "Arguments de la fonction f3 :"
22 echo "\$0 => $0"
23 echo "\$1 => $1"
24 echo "\$2 => $2"
25 echo "\$3 => $3"
26 echo "\$* => $*"
27 echo "\$# => $#"
28 }
29 echo "Arguments du programme principal :"
30 echo "\$0 => $0"
31 echo "\$1 => $1"
32 echo "\$2 => $2"
33 echo "\$3 => $3"
34 echo "\$* => $*"
35 echo "\$# => $#"
36 # Appel de la fonction f1 avec 3 arguments
37 f1 a b c
38 # Appel de la fonction f2 avec 3 arguments
39 f2 file.c 2000 500
40 # Appel de la fonction f3 avec 2 arguments provenant du programme principal
41 f3 $2 $3
42 exit 0
$
Appel du script fonction04.sh avec 3 arguments :
$ ./fonction04.sh arg1 arg2 arg3
Arguments du programme principal :
$0 => ./fonction04.sh
$1 => arg1
$2 => arg2
$3 => arg3
$* => arg1 arg2 arg3
$# => 3
Arguments de la fonction f1 :
$0 => ./fonction04.sh
$1 => a
$2 => b
$3 => c
$* => a b c
$# => 3
Arguments de la fonction f2 :
$0 => ./fonction04.sh
$1 => file.c
$2 => 2000
$3 => 500
$* => file.c 2000 500
$# => 3
Arguments de la fonction f3 :
$0 => ./fonction04.sh
$1 => arg2
$2 => arg3
$3 =>
$* => arg2 arg3
$# => 2
$
Comme n'importe quelle commande renvoyant un résultat, une fonction peut également être placée à l'intérieur de caractères de substitution de commande `` ou $( ).
Exemple :
$ nl fonction05.sh
1 #!/bin/bash
2 function getUid {
3 grep "^$1:" /etc/passwd | cut -d':' -f3
4 }
5 # Initialisation de la variable globale uid
6 uid=""
7 # Appel de la fonction getUid avec l'argument du programme principal
8 # Juste pour l'affichage
9 getUid $1
10 # Affectation du résultat de la fonction getUid à la variable uid
11 uid=$(getUid $1)
12 if [[ $uid != "" ]]
13 then
14 echo "L'utilisateur $1 a pour UID : $uid"
15 else
16 echo "L'utilisateur $1 n'existe pas"
17 fi
18 exit 0
$ ./fonction05.sh root
0
L'utilisateur root a pour UID : 0
$
Exemple d'un script reprenant toutes les commandes et fonctions vues précédement
$ nl fonction06.sh
1 #!/bin/bash
2 # Pour faire une pause
3 function pause {
4 echo "Appuyer sur Entrée pour continuer"
5 read x
6 }
7 # Pour savoir si un utilisateur existe
8 function existUser {
9 grep -qi "^$1:" /etc/passwd && return 0
10 return 1
11 }
12 # Pour connaitre l'uid de l'utilisateur
13 function getUid {
14 grep -i "^$1:" /etc/passwd | cut -d':' -f3
15 }
16 # Initialisation des variables globales
17 uid=""
18 user=""
19 choix=""
20 while true
21 do
22 clear
23 echo "- 1 - Savoir si un utilisateur existe"
24 echo "- 2 - Connaitre l'UID d'un utilisateur"
25 echo "- 3 - Fin"
26 echo -e "Votre choix : \c"
27 read choix
28 if [[ $choix = @(1|2) ]] ; then
29 echo -e "Saisir le nom d'un utilisateur : \c"
30 read user
31 fi
32 case $choix in
33 1) if existUser $user ; then
34 echo "L'utilisateur $user existe"
35 else
36 echo "l'utilisateur $user n'existe pas"
37 fi
38 ;;
39 2) if existUser $user ; then
40 uid=$(getUid $user)
41 echo "l'UID de l'utilisateur $user est : $uid"
42 else
43 echo "L'utilisateur $user n'existe pas"
44 fi
45 ;;
46 3) exit 0
47 ;;
48 esac
49 pause
50 done
$