Aller au contenu principal

Fonctions


Table des matières

  1. Définition de fonctions
  2. Arguments et paramètres
  3. Valeurs de retour
  4. Variables locales et scope
  5. Fonctions avancées
  6. Exercices pratiques


1 - Définition de fonctions

Syntaxe

# Méthode 1 (recommandée)
nom_fonction() {
# commandes
}

# Méthode 2 (avec mot-clé function)
function nom_fonction {
# commandes
}

# Méthode 3 (combinée)
function nom_fonction() {
# commandes
}

Exemple simple

#!/bin/bash

# Définir la fonction
dire_bonjour() {
echo "Bonjour, monde!"
}

# Appeler la fonction
dire_bonjour

Fonction avec logique

#!/bin/bash

afficher_date() {
echo "=== Date actuelle ==="
date '+%Y-%m-%d %H:%M:%S'
echo "===================="
}

# Utilisation
afficher_date

Ordre de définition

#!/bin/bash

# ERREUR: fonction appelée avant définition
ma_fonction # bash: ma_fonction: command not found

ma_fonction() {
echo "Hello"
}

# CORRECT: définir avant d'appeler
ma_fonction() {
echo "Hello"
}

ma_fonction # Fonctionne

🔝 Retour à la table des matières



2 - Arguments et paramètres

Passage d'arguments

saluer() {
echo "Bonjour, $1!"
}

saluer "Alice" # Bonjour, Alice!
saluer "Bob" # Bonjour, Bob!

Variables d'arguments

VariableDescription
$1, $2...Arguments positionnels
$#Nombre d'arguments
$@Tous les arguments (séparés)
$*Tous les arguments (chaîne)
$0Nom du script (pas de la fonction)

Exemple complet

afficher_info() {
echo "Fonction appelée avec $# arguments"
echo "Argument 1: $1"
echo "Argument 2: $2"
echo "Tous: $@"
}

afficher_info "hello" "world" "!"
# Fonction appelée avec 3 arguments
# Argument 1: hello
# Argument 2: world
# Tous: hello world !

Arguments avec valeurs par défaut

creer_utilisateur() {
local nom="${1:-guest}"
local home="${2:-/home/$nom}"
local shell="${3:-/bin/bash}"

echo "Création: $nom"
echo " Home: $home"
echo " Shell: $shell"
}

creer_utilisateur # Valeurs par défaut
creer_utilisateur "alice" # Nom personnalisé
creer_utilisateur "bob" "/opt/bob" # Nom et home

Validation des arguments

diviser() {
if [ $# -ne 2 ]; then
echo "Usage: diviser <dividende> <diviseur>" >&2
return 1
fi

if [ "$2" -eq 0 ]; then
echo "Erreur: division par zéro" >&2
return 1
fi

echo $(( $1 / $2 ))
}

diviser 10 2 # 5
diviser 10 0 # Erreur
diviser 10 # Usage

🔝 Retour à la table des matières



3 - Valeurs de retour

Code de retour avec return

est_pair() {
if (( $1 % 2 == 0 )); then
return 0 # Succès (vrai en shell)
else
return 1 # Échec (faux en shell)
fi
}

if est_pair 4; then
echo "4 est pair"
fi

if ! est_pair 3; then
echo "3 est impair"
fi

Codes de retour conventionnels

CodeSignification
0Succès
1Erreur générale
2Mauvaise utilisation
126Permission refusée
127Commande non trouvée

Retourner une valeur via stdout

calculer_somme() {
local somme=0
for n in "$@"; do
((somme += n))
done
echo $somme # "Retourne" via stdout
}

# Capturer le résultat
resultat=$(calculer_somme 1 2 3 4 5)
echo "Somme: $resultat" # Somme: 15

Combiner code de retour et valeur

chercher_fichier() {
local pattern="$1"
local dir="${2:-.}"

local result=$(find "$dir" -name "$pattern" -type f 2>/dev/null | head -1)

if [ -n "$result" ]; then
echo "$result" # Valeur via stdout
return 0 # Succès
else
return 1 # Échec
fi
}

# Utilisation
if fichier=$(chercher_fichier "*.conf" /etc); then
echo "Trouvé: $fichier"
else
echo "Non trouvé"
fi

🔝 Retour à la table des matières



4 - Variables locales et scope

Variables globales vs locales

#!/bin/bash

global_var="Je suis globale"

ma_fonction() {
local local_var="Je suis locale"
global_var="Modifiée dans la fonction"

echo "Dans fonction: $global_var"
echo "Dans fonction: $local_var"
}

ma_fonction
echo "Après fonction: $global_var" # Modifiée
echo "Après fonction: $local_var" # (vide)

Le mot-clé local

compteur() {
local count=0 # Variable locale
for i in {1..5}; do
((count++))
done
echo $count
}

count=100
resultat=$(compteur)
echo "Résultat: $resultat" # 5
echo "Count global: $count" # 100 (non modifié)

Bonnes pratiques

#!/bin/bash

# BONNE PRATIQUE: toujours utiliser local
traiter_fichier() {
local fichier="$1"
local contenu
local ligne

contenu=$(cat "$fichier")
# ...
}

# MAUVAISE PRATIQUE: variables globales implicites
traiter_fichier_mauvais() {
fichier="$1" # Pollue l'espace global
contenu=$(cat "$fichier")
}

🔝 Retour à la table des matières



5 - Fonctions avancées

Récursivité

factorielle() {
local n=$1
if (( n <= 1 )); then
echo 1
else
local prev=$(factorielle $((n - 1)))
echo $((n * prev))
fi
}

echo "5! = $(factorielle 5)" # 120

Fonctions dans des fichiers

# lib/utils.sh
log_info() {
echo "[INFO] $(date '+%H:%M:%S') $*"
}

log_error() {
echo "[ERROR] $(date '+%H:%M:%S') $*" >&2
}

die() {
log_error "$@"
exit 1
}

# main.sh
#!/bin/bash
source lib/utils.sh

log_info "Démarrage du script"
# ...

Bibliothèque de fonctions

#!/bin/bash
# lib/string_utils.sh

# Convertir en majuscules
to_upper() {
echo "$1" | tr '[:lower:]' '[:upper:]'
}

# Convertir en minuscules
to_lower() {
echo "$1" | tr '[:upper:]' '[:lower:]'
}

# Supprimer les espaces
trim() {
echo "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
}

# Vérifier si commence par
starts_with() {
[[ "$1" == "$2"* ]]
}

# Vérifier si termine par
ends_with() {
[[ "$1" == *"$2" ]]
}

Fonctions avec options

log() {
local level="INFO"
local message=""

while [[ $# -gt 0 ]]; do
case $1 in
-l|--level)
level="$2"
shift 2
;;
*)
message="$1"
shift
;;
esac
done

echo "[$level] $(date '+%H:%M:%S') $message"
}

log "Message simple"
log -l ERROR "Une erreur"
log --level WARNING "Attention"

🔝 Retour à la table des matières



6 - Exercices pratiques

Exercice 1 : Fonction de validation

# Créez une fonction is_number qui vérifie
# si l'argument est un nombre entier
Solution
is_number() {
[[ "$1" =~ ^-?[0-9]+$ ]]
}

if is_number "123"; then echo "OK"; fi
if is_number "-42"; then echo "OK"; fi
if ! is_number "abc"; then echo "Pas un nombre"; fi

Exercice 2 : Fonction de logging

# Créez une fonction log qui:
# - Prend un niveau (INFO, WARN, ERROR)
# - Affiche avec timestamp
# - ERROR vers stderr
Solution
log() {
local level="${1:-INFO}"
shift
local message="$*"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

if [[ "$level" == "ERROR" ]]; then
echo "[$timestamp] [$level] $message" >&2
else
echo "[$timestamp] [$level] $message"
fi
}

log INFO "Démarrage"
log WARN "Attention"
log ERROR "Erreur critique"

Quiz

Q1. Comment déclarer une variable locale dans une fonction ?

Réponse

local ma_variable="valeur"

Q2. Comment retourner une valeur depuis une fonction ?

Réponse

Via echo (stdout) et capture avec $(fonction), ou via return pour un code de retour (0-255).

Q3. Que retourne return 0 ?

Réponse

Succès (équivalent à "vrai" dans un test if)

🔝 Retour à la table des matières



Points clés à retenir

  • Définir avec nom() { } ou function nom { }
  • Arguments: $1, $2, $#, $@
  • Toujours utiliser local pour les variables internes
  • return N pour le code de retour (0=succès)
  • echo pour retourner des valeurs (capturer avec $())
  • Définir les fonctions avant de les appeler
  • Utiliser source pour importer des bibliothèques

🔝 Retour à la table des matières


← Chapitre précédent | Chapitre suivant : Manipulation de texte →