Parcours
/
Bash
Bash
/
Programme
/
Conditionnelles
Co

Conditionnelles en Bash

{one: "%{count} exercice", many: "%{count} d'exercices", other: "%{count} exercices"}

À propos de Conditionnelles

La notion de vérité en Bash

Bash ne connaît pas la notion de valeurs booléennes. Il y a des strings et des nombres, ainsi que des tableaux de strings ou de nombres. Alors, comment les commandes conditionnelles gèrent-elles le vrai et le faux ?

Le statut de sortie

Les commandes produisent un statut de sortie lorsqu'elles se terminent. Un statut de sortie est un entier compris entre 0 et 255 inclus. Bash considère qu'un statut de sortie zéro représente une réussite. Tout autre statut de sortie représente un échec.

Cela vaut pour toutes les commandes, y compris les commandes intégrées de Bash, les mots-clés et les fonctions.

La commande if

La syntaxe de base de la commande if est la suivante :

if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi

Elle commence par if ; les commandes de condition sont séparées des commandes de « succès » par then ; et elle se termine par fi. La clause else est facultative.

CONDITIONAL_COMMANDS peut être une seule commande ou une liste de commandes.

Les CONDITIONAL_COMMANDS sont exécutées, et

  • si le statut de sortie est zéro (réussite), alors les TRUE_COMMANDS sont exécutées.
  • si le statut de sortie est non nul (échec), alors les FALSE_COMMANDS sont exécutées, si elles sont présentes.

On peut enchaîner des branches avec elif

if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi

Il faut un point-virgule ou un saut de ligne avant les mots then, elif, else et fi.

Pour insister : c'est le statut de sortie des commandes conditionnelles qui contrôle le déroulement. Par exemple, grep renvoie 0 si une correspondance est trouvée, et 1 si aucune correspondance n'est trouvée. L'option -q supprime la sortie et ne produit que le statut de sortie.

if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi

Les commandes [ et test

Il n'y a pas de syntaxe particulière autour des CONDITIONAL_COMMANDS. Tu as peut-être l'habitude de voir des instructions if qui ressemblent à ceci :

if [ "$password" = "secure" ]; then
    echo "Welcome!"
fi

[ n'est pas une syntaxe particulière. C'est une commande qui évalue l'expression conditionnelle et se termine avec un statut de réussite ou d'échec. Comme pour toutes les commandes, un espace est obligatoire entre elle et ses arguments.

En réalité, [ est un synonyme de la commande test. Elles sont exactement identiques, sauf que le dernier argument de [ doit être ].

Les expressions conditionnelles

Entre [ et ], tu écris une expression conditionnelle. Voici quelques expressions conditionnelles typiques :

[ -f "$filename" ]             # file operations
[ "$string1" = "$string2" ]    # string comparisons
[ "$num1" -eq "$num2" ]        # arithmetic comparisons

Il existe beaucoup d'autres opérations ; elles sont listées dans la section Bash Conditional Expressions du manuel.

Note

Dans les exemples ci-dessus, remarque que toutes les variables sont entre guillemets. Les commandes test et [ sont des commandes ordinaires, où les arguments sont soumis au découpage des mots et à l'expansion des noms de fichiers comme pour n'importe quelle autre commande.

C'est important à souligner, car les expressions conditionnelles sont évaluées différemment selon le nombre d'arguments que tu fournis :

  • 0 argument : le statut de sortie est non nul (échec)
  • 1 argument : le statut de sortie est zéro (réussite) si l'argument n'est pas vide, non nul s'il est vide.
  • 2 arguments : le premier argument doit être un opérateur unaire (comme [ -z "$name" ]), ou un ! (qui inverse le statut du test à 1 argument)
  • et bien d'autres.

Tu peux obtenir des résultats inattendus si tu oublies de mettre les guillemets :

str=""

# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi

# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi

Le mot-clé [[

La construction conditionnelle [[...]] n'est pas une commande, c'est un mot-clé. Cela signifie que, bien qu'elle soit traitée comme n'importe quelle autre commande, elle obéit à des règles d'analyse syntaxique particulières. Ce qui est particulier avec [[, c'est que les variables qui y sont développées ne sont pas soumises au découpage des mots ni à l'expansion des noms de fichiers. Cette commande se comporte donc comme tu l'attends, même sans guillemets.

if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi

[[ prend en charge toutes les expressions conditionnelles que test et [ savent gérer. De plus, [[ fournit

  • l'opérateur de correspondance par expression régulière =~,
  • == et != qui agissent comme un opérateur de correspondance de motif glob,
  • && et || comme opérateurs logiques (règle d'analyse particulière),
  • < et > comme opérateurs de comparaison de strings « nus » (règle d'analyse particulière : comme ce sont des symboles de redirection, ils doivent être échappés dans [).

On considère généralement que ces fonctionnalités particulières apportent tant d'avantages que [[ devrait être utilisé exclusivement. (Par exemple, le Google Shell Style Guide.)

La commande case

case est une autre commande de contrôle de flux. Elle ressemble à une instruction « switch » dans d'autres langages.

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

WORD est comparée à chaque PATTERN. Quand l'une correspond, les COMMANDS sont exécutées.

read -p "Guess the secret word: " word
case "$word" in
    secret) echo "Yes, you guessed it!" ;;
    ??????) echo "That's the right number of letters." ;;
    s*)     echo "You guessed the first letter." ;;
    *)      echo "Not even close! Try again." ;;
esac

Chaque clause COMMANDS doit se terminer par deux points-virgules, ;;.

Note
  1. Il existe des variantes qui gèrent la poursuite de l'exécution d'une clause à l'autre, ainsi que la continuation de la correspondance de motif. Consulte le manuel pour plus de détails.
  2. Rappelle-toi que nous avons parlé des motifs dans la section Filename Expansion du concept Quoting.
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet