Tests et conditions

Tu sais récupérer les variables envoyées en paramètres à ton script, tu sais en créer, tu sais faire un peu de maths et afficher toutes ces variables. C'est bien. Mais que dirais-tu de rendre tes scripts un peu plus vivants ? D'avoir des exécutions différentes selon ce que tu envoies en paramètres ? C'est déjà plus intéressant.

Conditions

Une condition en shell est un test qui va renvoyer Vrai ou Faux. Si c'est Vrai, alors le script va emprunter un chemin d'exécution, si c'est Faux, alors le script va emprunter un autre chemin d'exécution.

Test

Tu peux tester plusieurs choses en shell : les nombres, les chaînes de caractères, l'existence de fichier, les exécutions d'autres programmes.

Je t'invite à lire le man 1 test qui liste tous les tests possibles.

Comme tu peux le vois, on peut combiner les tests avec les portes logiques AND et OR.

Par exemple pour tester une chaîne de caractères, tu utilises le test

[ chaine1 = chaine2 ]

Ce test renverra Faux.

Attention à bien laisser des ESPACES ' ' entre le signe '$' et à côté des crochets '[' et ']'. Si tu ne laisses pas d'espaces, le shell ne comprendra pas que c'est un test et boguera.

Protection

Avant de montrer des exemples, je dois te montrer une technique de protection des scripts pour éviter des crashs embêtants.

#!/bin/sh

mot_de_passe=$1

if [ $mot_de_passe = "pediluve" ]
then
    echo "Ouverture de la porte secrète"
else
    echo "Mauvais mot de passe"
fi

Exécute ce script sans lui envoyer de paramètre.

$ ./script.sh
./script.sh: line 5: [: =: unary operator expected
Mauvais mot de passe
$

Que s'est-il passé ?

La variable n'a pas de valeur, le shell a donc lu la ligne avec le test littéralement de cette manière :

if [ = "pediluve" ]

Ceci n'est pas du shell valide. Il faut une valeur avant le signe '='.

Tu peux protéger ta variable en lui mettant des double quotes.

#!/bin/sh

mot_de_passe=$1

if [ "$mot_de_passe" = "pediluve" ]
then
    echo "Ouverture de la porte secrète"
else
    echo "Mauvais mot de passe"
fi

Si tu exécutes le script sans paramètre, voici ce que le shell lit.

if [ "" = "pediluve" ]

Le shell comprend alors qu'il teste une chaîne de caractères vide avec "pediluve".

Exemples

if elif else

Avant de te montrer de réels exemples, tu vas apprendre à enchainer les tests.

if sert à tester une ou plusieurs conditions. Si tout est Vrai, alors le code qui suit sera exécuté.

elif est la concaténation de else if. Il faut aussi mettre une condition, et si la condition est Vraie, alors le code qui suit sera exécuté. Tu peux enchainer autant de elif que tu veux. Tu n'es pas obligé d'utiliser elif quand tu fais des tests.

else contient du code qui sera exécuté si tous les tests précédents étaient Faux. Il ne faut pas lui mettre de test.

#!/bin/sh

# Si le code secret n'est pas bon
# on écrit sur stderr que le code est faux
# et on quitte le script avec l'exit status 1
if [ "$1" != "super_mot_de_passe" ]
then
    echo "Mauvais mot de passe" >&2
    exit 1
fi

if [ "$2" = "gelules" ]
then
    echo "Bonjour maitre"
elif [ "$2" = "pediluvien" ]
then
    echo "Bonjour jeune apprenti"
elif [ "$2" = "piscinien" ]
then
    echo "Bonjour, tu viens te rafraichir la mémoire ?"
else
    echo "Tu m'es inconnu"
fi

Petit jeu vidéo

Pour apprendre à faire des tests, au lieu de t'énumérer tous les tests possibles, je préfère te montrer plein d'exemples différents. A toi ensuite de lire le man 1 test pour compléter tes connaissances.

Imaginons que tu codes un petit jeu vidéo en shell.

#!/bin/sh

# Si le nombre d'arguments n'est pas 2
if [ $# -ne 2 ]
then
    echo "Usage: $0 LOGIN SALLE_DE_TP" >&2
    exit 1
fi

login=$1
tp=$2
save_file=sauvegarde.txt

# Si le fichier de sauvegarde n'existe pas et que c'est bien un pédiluvien qui
# joue au jeu, on crée le fichier de sauvegarde
if [ ! -f "$save_file" ] -a [ "$login" != "gelules" ]
then
    touch "$save_file"
fi

# Exception pour le maitre de jeu
if [ "$login" = "gelules" ]
then
    echo "TP gelules dans 'salle secrète'" >> "gelules_sauvegarde.txt"
    exit
fi

if [ "$tp" = "donjon" ]
then
    echo "TP $login dans 'donjon'" >> "$save_file"
    exit
elif [ "$tp" = "tour" ]
then
    echo "TP $login dans 'tour'" >> "$save_file"
    exit
elif [ "$tp" = "chambre" ]
then
    echo "TP $login dans 'chambre'" >> "$save_file"
    exit
else
    echo "Mauvaise TP" >&2
    exit 1
fi

Je te laisse essayer le script.

Il n'est pas optimisé du tout. Comme tu peux le voir, il y a du code qui se répète. On retrouve beaucoup de fois

echo "TP $login dans 'LIEU'" >> "$save_file"

mais c'est un problème pour plus tard. Pour l'instant il faut que tu apprennes à jouer avec les tests.

Je t'invite à regarder plus en détail comment tester les nombres. Dans mon exemple je teste si le nombre d'argument est Not Equal à 2. Mais tu peux tester une égalité, si le nombre est strictement inférieur ou inférieur ou égal, et pareil avec la supériorité.