HOWTO · Bash
Attribuer une valeur par défaut dans Bash
Cet article présentera différentes approches pour fournir une valeur par défaut à une variable dans bash
Sur cette page
Utilisez l’expansion de paramètres de Bash pour choisir une valeur de repli lors de l’expansion d’une valeur, ou pour affecter cette valeur à une variable. Pour un argument de script, ${1:-default_value} utilise default_value lorsque le premier argument ne fournit aucune valeur exploitable. La distinction entre choisir et affecter est importante : :- ne modifie pas le paramètre, contrairement à :=.
Utiliser l’expansion de paramètres de Bash pour les valeurs par défaut
Exécutez cet exemple. Le code et les libellés de sortie affichés dans les blocs ci-dessous restent en anglais :
#!/usr/bin/env bash
value=${1:-"default_value"}
printf 'value=%s\n' "$value"
value=default_value
Sans premier argument, l’expansion sélectionne default_value et la commande affiche la valeur obtenue. Le résultat entre guillemets est affecté à value ; les commandes suivantes peuvent ainsi l’utiliser sans répéter l’expression de repli. Mettre "$value" entre guillemets permet de le conserver comme un seul argument, même s’il contient des espaces. Remplacez $1 par un nom de variable tel que config_file pour appliquer le même principe à une variable du shell.
Distinguer les paramètres non définis des paramètres vides
Dans Bash, un paramètre non défini n’a aucune valeur affectée ; un paramètre vide (ou nul) est défini avec une valeur de zéro caractère. L’opérateur sans deux-points et celui qui en comporte un traitent ces états différemment. ${parameter-word} substitue word uniquement si parameter n’est pas défini. ${parameter:-word} substitue word si le paramètre n’est pas défini ou s’il est nul. Dans les deux formes, la valeur de repli est seulement développée : le paramètre lui-même reste inchangé.
Par exemple, ${name-guest} conserve name lorsque sa valeur est une chaîne vide, tandis que ${name:-guest} substitue guest dans ce cas. Si seul un paramètre non défini doit déclencher une valeur de repli, utilisez la forme sans deux-points. Si un paramètre non défini ou vide doit la déclencher, utilisez la forme avec deux-points. Ces opérateurs fonctionnent aussi avec les paramètres positionnels ; ${1:-guest} permet donc de choisir facilement un argument par défaut.
La comparaison suivante utilise une variable distincte pour chaque opérateur afin qu’une affectation dans un cas ne modifie pas le résultat du suivant. La valeur affichée <unset> signifie que le paramètre reste non défini ; un champ vide signifie qu’il est défini comme chaîne vide. Dans les groupes unset et empty, = n’affecte une valeur que si le paramètre n’est pas défini, tandis que := l’affecte si le paramètre n’est pas défini ou est vide. Ni - ni :- n’affecte de valeur au paramètre. Lorsque la variable contient déjà ready, les quatre formes la préservent.
Exécutez cet exemple de Bash. Les libellés et les sorties affichés dans les blocs ci-dessous restent en anglais :
#!/usr/bin/env bash
unset u_dash u_colon_dash u_equal u_colon_equal
u_dash_result=${u_dash-fallback}
u_colon_dash_result=${u_colon_dash:-fallback}
u_equal_result=${u_equal=fallback}
u_colon_equal_result=${u_colon_equal:=fallback}
printf 'unset results: -=%s, :-=%s, ==%s, :=%s\n' "$u_dash_result" "$u_colon_dash_result" "$u_equal_result" "$u_colon_equal_result"
printf 'unset variables: -=%s, :-=%s, ==%s, :=%s\n' "${u_dash-<unset>}" "${u_colon_dash-<unset>}" "${u_equal-<unset>}" "${u_colon_equal-<unset>}"
e_dash=''
e_colon_dash=''
e_equal=''
e_colon_equal=''
e_dash_result=${e_dash-fallback}
e_colon_dash_result=${e_colon_dash:-fallback}
e_equal_result=${e_equal=fallback}
e_colon_equal_result=${e_colon_equal:=fallback}
printf 'empty results: -=%s, :-=%s, ==%s, :=%s\n' "$e_dash_result" "$e_colon_dash_result" "$e_equal_result" "$e_colon_equal_result"
printf 'empty variables: -=%s, :-=%s, ==%s, :=%s\n' "${e_dash-<unset>}" "${e_colon_dash-<unset>}" "${e_equal-<unset>}" "${e_colon_equal-<unset>}"
s_dash=ready
s_colon_dash=ready
s_equal=ready
s_colon_equal=ready
s_dash_result=${s_dash-fallback}
s_colon_dash_result=${s_colon_dash:-fallback}
s_equal_result=${s_equal=fallback}
s_colon_equal_result=${s_colon_equal:=fallback}
printf 'set results: -=%s, :-=%s, ==%s, :=%s\n' "$s_dash_result" "$s_colon_dash_result" "$s_equal_result" "$s_colon_equal_result"
printf 'set variables: -=%s, :-=%s, ==%s, :=%s\n' "$s_dash" "$s_colon_dash" "$s_equal" "$s_colon_equal"
unset results: -=fallback, :-=fallback, ==fallback, :=fallback
unset variables: -=<unset>, :-=<unset>, ==fallback, :=fallback
empty results: -=, :-=fallback, ==, :=fallback
empty variables: -=, :-=, ==, :=fallback
set results: -=ready, :-=ready, ==ready, :=ready
set variables: -=ready, :-=ready, ==ready, :=ready
Affecter une valeur par défaut avec :=
Les opérateurs d’affectation suivent la même distinction liée aux deux-points. ${parameter=word} affecte word à parameter uniquement si celui-ci n’est pas défini. ${parameter:=word} l’affecte si le paramètre n’est pas défini ou s’il est nul. Le résultat développé est la valeur affectée, et les références suivantes à cette variable voient cette valeur. Utilisez := lorsque le script doit initialiser une variable une fois, puis s’appuyer sur sa valeur ; utilisez :- lorsque vous avez besoin d’une valeur de repli pour une seule expansion, sans modifier la variable. La comparaison ci-dessus montre les deux conditions de chaque opérateur ainsi que les valeurs des paramètres après l’expansion.
Par exemple, : "${config_dir:=/etc/my-app}" affecte /etc/my-app à config_dir si cette variable n’est pas définie ou est vide. Le : placé au début est la commande nulle de Bash : elle développe ses arguments puis les ignore. L’affectation se produit pendant l’expansion de l’argument, et non parce que : interpréterait une affectation. Les formes = et := nécessitent un nom de variable auquel une valeur peut être affectée ; elles ne peuvent pas affecter de paramètres positionnels ni spéciaux. Pour fournir une valeur par défaut à $1, copiez l’expansion dans une variable ordinaire, comme dans le premier exemple.
Choisir entre l’expansion de paramètres et if
L’expansion de paramètres est concise lorsqu’une seule règle concernant les paramètres non définis ou nuls suffit. Choisissez if lorsque la valeur de repli dépend de plusieurs conditions, qu’elle doit être validée ou que différentes actions sont nécessaires. Par exemple, pour distinguer mode non défini de mode défini mais vide, vérifiez s’il est défini avec ${mode+x}, puis traitez chaque état dans une branche distincte. Une instruction if permet aussi facilement d’afficher un diagnostic ou de renvoyer une erreur avant d’affecter une valeur.
Si un paramètre non défini ou vide doit sélectionner la même valeur de repli, une condition if simple peut utiliser [[ -z ${mode-} ]] ; si seul un paramètre non défini doit la sélectionner, vérifiez plutôt [[ -z ${mode+x} ]]. Le test -z vérifie si son opérande chaîne a une longueur nulle ; ${mode-} lui fournit donc une chaîne sûre même lorsque mode n’est pas défini. Préférez [[ ... ]] dans les scripts Bash, et mettez les valeurs entre guillemets lorsque vous les transmettez à des commandes.
Pièges courants et exemples pratiques
Ne confondez pas expansion et affectation : value=${input:-guest} définit value, mais laisse input inchangée ; input=${input:=guest} initialise input elle-même. De plus, les deux-points dans :- et := font partie de la syntaxe d’expansion de paramètres. Ils ne désignent pas la commande distincte : et ne signifient pas que les arguments sont ignorés. La commande : peut servir à déclencher une expansion avec affectation, comme ci-dessus, mais c’est l’expansion qui applique la valeur par défaut.
Choisissez l’opérateur en fonction de la règle voulue pour l’entrée. Utilisez - ou = si une valeur vide intentionnelle doit être conservée, et :- ou := si une valeur vide doit être considérée comme manquante. Si une variable peut contenir des espaces, mettez ses utilisations ultérieures entre guillemets, par exemple printf '%s\n' "$config_dir". Pour attribuer une valeur par défaut à un argument positionnel une seule fois, affectez ${1:-guest} à une variable nommée. Pour effectuer une validation, appliquer plusieurs règles de repli ou afficher des messages d’erreur destinés à l’utilisateur, utilisez une instruction if afin d’expliciter chaque décision et chaque action.