Les fonctions peuvent récupérer des arguments qui leur sont passés et renvoyer un code de sortie au script pour utilisation ultérieure.
nom_fonction $arg1 $arg2 |
La fonction se réfère aux arguments passés par leur position (comme si ils étaient des paramètres positionnels), c'est-à-dire $1, $2, et ainsi de suite.
Exemple 23-2. Fonction prenant des paramètres
#!/bin/bash
# Functions and parameters
DEFAUT=defaut # Valeur par défaut.
fonc2 () {
if [ -z "$1" ] # Est-ce que la taille du paramètre
# #1 a une taille zéro?
then
echo "-Le paramètre #1 a une taille nulle.-" # Ou aucun paramètre n'est passé.
else
echo "-Le paramètre #1 est \"$1\".-"
fi
variable=${1-$DEFAUT} # Que montre la substitution de
echo "variable = $variable" #+ paramètre?
# ---------------------------
# Elle distingue entre pas de
#+ paramètre et un paramètre nul.
if [ "$2" ]
then
echo "-Le paramètre #2 est \"$2\".-"
fi
return 0
}
echo
echo "Aucun argument."
fonc2 # Appelé sans argument
echo
echo "Argument de taille nulle."
fonc2 "" # Appelé avec un paramètre de taille zéro
echo
echo "Paramètre nul."
fonc2 "$parametre_non_initialise" # Appelé avec un paramètre non initialisé
echo
echo "Un paramètre."
fonc2 first # Appelé avec un paramètre
echo
echo "Deux paramètres."
fonc2 first second # Appelé avec deux paramètres
echo
echo "\"\" \"second\" comme argument."
fonc2 "" second # Appelé avec un premier paramètre de taille nulle,
echo # et une chaîne ASCII pour deuxième paramètre.
exit 0 |
![]() | La commande shift fonctionne sur les arguments passés aux fonctions (voir Exemple 34-10). |
![]() | En contraste avec certains autres langages de programmation, les scripts shell passent normalement seulement des paramètres par valeur aux fonctions. [1] Les noms de variables (qui sont réellement des pointeurs), s'ils sont passés en tant que paramètres de fonctions, seront traités comme des chaînes de caractères et ne pourront être déréférencés. Les fonctions interprètent leur arguments littéralement. |
Les fonctions renvoient une valeur, appellée un code (ou état) de sortie. Le code de sortie peut être explicitement spécifié par une instruction return, sinon il s'agit du code de sortie de la dernière commande de la fonction (0 en cas de succès et une valeur non nulle sinon). Ce status de sortie peut être utilisé dans le script en le référanceant à l'aide de la variable $?. Ce mécanisme permet effectivement aux fonctions des scripts d'avoir une << valeur de retour >> similaire à celle des fonctions C.
Termine une fonction. Une commande return [2] prend optionnellement un argument de type entier, qui est renvoyé au script appelant comme << code de sortie >> de la fonction, et ce code de sortie est affecté à la variable $?.
Exemple 23-3. Maximum de deux nombres
#!/bin/bash
# max.sh: Maximum de deux entiers.
E_PARAM_ERR=-198 # Si moins de deux paramètres passés à la fonction.
EGAL=-199 # Code de retour si les deux paramètres sont égaux.
max2 () # Envoie le plus important des deux entiers.
{ # Note: les nombres comparés doivent être plus petit que 257.
if [ -z "$2" ]
then
return $E_PARAM_ERR
fi
if [ "$1" -eq "$2" ]
then
return $EGAL
else
if [ "$1" -gt "$2" ]
then
return $1
else
return $2
fi
fi
}
max2 33 34
return_val=$?
if [ "$return_val" -eq $E_PARAM_ERR ]
then
echo "Vous devez donner deux arguments à la fonction."
elif [ "$return_val" -eq $EGAL ]
then
echo "Les deux nombres sont identiques."
else
echo "Le plus grand des deux nombres est $return_val."
fi
exit 0
# Exercice (facile):
# ---------------
# Convertir ce script en une version interactive,
#+ c'est-à-dire que le script vous demande les entrées (les deux nombres). |
![]() | Pour qu'une fonction renvoie une chaîne de caractères ou un tableau, utilisez une variable dédiée.
|
Exemple 23-4. Convertire des nombres en chiffres romains
#!/bin/bash
# Conversion d'un nombre arabe en nombre romain
# Echelle: 0 - 200
# C'est brut, mais cela fonctionne.
# Etendre l'échelle et améliorer autrement le script est laissé en exercice.
# Usage: roman nombre-a-convertir
LIMITE=200
E_ERR_ARG=65
E_HORS_ECHELLE=66
if [ -z "$1" ]
then
echo "Usage: `basename $0` nombre-a-convertir"
exit $E_ERR_ARG
fi
num=$1
if [ "$num" -gt $LIMITE ]
then
echo "En dehors de l'échelle!"
exit $E_HORS_ECHELLE
fi
vers_romain () # Doit déclarer la fonction avant son premier appel.
{
nombre=$1
facteur=$2
rchar=$3
let "reste = nombre - facteur"
while [ "$reste" -ge 0 ]
do
echo -n $rchar
let "nombre -= facteur"
let "reste = nombre - facteur"
done
return $nombre
# Exercixe:
# --------
# Expliquer comment fonctionne cette fonction.
# Astuce: division par une soustraction successive.
}
vers_romain $nombre 100 C
nombre=$?
vers_romain $nombre 90 LXXXX
nombre=$?
vers_romain $nombre 50 L
nombre=$?
vers_romain $nombre 40 XL
nombre=$?
vers_romain $nombre 10 X
nombre=$?
vers_romain $nombre 9 IX
nombre=$?
vers_romain $nombre 5 V
nombre=$?
vers_romain $nombre 4 IV
nombre=$?
vers_romain $nombre 1 I
echo
exit 0 |
Voir aussi Exemple 10-28.
![]() | L'entier positif le plus grand qu'une fonction peut renvoyer est 256. La commande return est très liée au code de sortie, qui tient compte de cette limite particulière. Heureusement, il existe quelques astuces pour ces situations réclamant une valeur de retour sur un grand entier. Exemple 23-5. Tester les valeurs de retour importantes dans une fonction
Comme nous l'avons vu, une fonction peut retourner une valeur négative importante. Ceci permet aussi de retourner un grand entier positif, en utilisant un peu d'astuce. Un autre moyen d'accomplir ceci est d'affecter simplement le << code de retour >> à une variable globale.
Exemple 23-6. Comparer deux grands entiers
Voir aussi Exemple A-8. Exercice: Utiliser ce que nous venons d'apprendre, étendre l'exemple précédent sur le nombres romains pour accepter une entrée arbitrairement grande. |
Une fonction est essentiellement un bloc de code, ce qui signifie que stdin peut être redirigé (comme dans Exemple 3-1).
Exemple 23-7. Vrai nom pour un utilisateur
#!/bin/bash
# A partir du nom utilisateur, obtenir le "vrai nom" dans /etc/passwd.
NBARGS=1 # Attend un arg.
E_MAUVAISARGS=65
fichier=/etc/passwd
modele=$1
if [ $# -ne "$NBARGS" ]
then
echo "Usage: `basename $0` NOMUTILISATEUR"
exit $E_MAUVAISARGS
fi
partie_fichier () # Scanne le fichier pour trouver modele, l'affichage correct
# se fait sur la ligne en question.
{
while read ligne # while n'a pas nécessairement besoin d'une "[ condition]"
do
echo "$ligne" | grep $1 | awk -F":" '{ print $5 }'
# awk utilise le délimiteur ":".
done
} <$fichier # Redirige le stdin de la fonction.
partie_fichier $modele
# Oui, le script entier peut être réduit en
# grep MODELE /etc/passwd | awk -F":" '{ print $5 }'
# ou
# awk -F: '/MODELE/ {print $5}'
# ou
# awk -F: '($1 == "nomutilisateur") { print $5 }' # vrai nom à partir du nom utilisateur
# Néanmoins, ce n'est pas aussi instructif.
exit 0 |
Il existe une autre méthode, certainement moins compliquée , de rediriger le stdin d'une fonction. Celle-ci fait intervenir la redirection de stdin vers un bloc de code entre accolades contenu à l'intérieur d'une fonction.
# Au lieu de:
Function ()
{
...
} < fichier
# Essayez ceci:
Function ()
{
{
...
} < fichier
}
# Similairement,
Function () # Ceci fonctionne.
{
{
echo $*
} | tr a b
}
Function () # Ceci ne fonctionne pas.
{
echo $*
} | tr a b # Un bloc de code intégré est obligatoire ici.
# Merci, S.C. |
| [1] | Les références de variables indirectes (voir Exemple 35-2) apportent une espèce de mécanisme peu pratique pour passer des pointeurs aux fonctions.
| |
| [2] | La commande return est une commande intégrée Bash. |
| Précédent | Sommaire | Suivant |
| Fonctions | Niveau supérieur | Variables locales |