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 |