Les substitutions de variables en bash

Accueil Tags Recherche

02 Mars 2023

Les substitutions de variables en bash

Découvrez les substitutions de variables, un outil puissant pour simplifier vos scripts.

Présentation

La substitution de variable (ou substitution de paramètre) est une syntaxe supportée par certains shells comme bash ou zsh, qui permet de modifier les variables sans faire appel à des commandes supplémentaires.

Pour utiliser cette syntaxe, vous devez vous assurer d’utiliser le bon shell (je vais utiliser bash dans cet article pour mes exemples). Deux possibilités s’offrent à vous :

  1. Ouvrir un nouveau terminal avec /bin/bash pour lancer les commandes
  2. Placer les commandes dans un fichier, en ajoutant le shebang #!/bin/bash à la première ligne

Valeurs par défaut

Utilisation la plus répandue, vous êtes probablement déjà tombés sur ce genre de code permettant d’utiliser une valeur par défaut, dans le cas où la variable serait indéfinie ou nulle (attention, une chaîne vide sera considérée comme nulle) :

LOG_LEVEL='debug'
echo "${LOG_LEVEL:-info}"
# debug
unset LOG_LEVEL
echo "${LOG_LEVEL:-info}"
# info

Il existe une variante permettant d’affecter une valeur par défaut. La différence avec l’exemple précédent est que la variable change de valeur lors du processus :

echo "${LOG_LEVEL:-info}"
# info
echo "$LOG_LEVEL"
#
echo "${LOG_LEVEL:=info}"
# info
echo "$LOG_LEVEL"
# info

Même si moins utile et répandue, l’opération inverse est aussi possible, où l’on remplace n’importe quelle valeur non nulle par une valeur alternative prédéfinie :

DEBUG_MODE='enabled'
echo "${DEBUG_MODE:+True}"
# True
unset DEBUG_MODE
echo "${DEBUG_MODE:+True}"
#

Vérification de définition de la variable

L’opérateur :? est lui aussi très utile pour vérifier la bonne définition des variables, il permet de déclencher un exit 1 avec un massage d’erreur dans le cas où la variable est indéfinie, ou nulle :

echo "${ENV:?Must be defined}"
# bash: ENV: Must be defined
# exit status 1

Longueur de la variable

Autre petite astuce, pour remplacer la commande wc -c :

USERNAME='zessx'
echo "${#USERNAME}"
# 5

Sous-chaînes

Grâce à l’opérateur :, il est possible d’extraire des sous-chaînes depuis votre variable. La syntaxe est très simple :

${VARIABLE:START:LENGTH}

À noter que le paramètre START peut être omis si vous souhaitez le début de la chaîne :

DATE="2022-03-02"
echo "${DATE::4}"
# 2022
echo "${DATE:5:2}"
# 03
echo "${DATE: -2:2}"
# 02

Préfixes de noms de variables

L’opérateur ! est un peu à part, car il permet de travailler sur le nom des variables, et non pas sur leur valeur :

USERNAME="zessx"
DATE_START="2022-01-01"
DATE_END="2022-03-02"
echo "${!DATE_*}"
# DATE_START DATE_END

Modification de la casse

Il est possible de mettre en majuscule le premier caractère :

USERNAME='zessx'
echo "${USERNAME^}"
# Zessx

Ou l’ensemble des caractères :

USERNAME='zessx'
echo "${USERNAME^^}"
# ZESSX

À l’inverse, vous pouvez utiliser l’opérateur , pour mettre en minuscule :

USERNAME='ZESSX'
echo "${USERNAME,}"
# zESSX
echo "${USERNAME,,}"
# zessx

L’opérateur utilise un motif implicite ?, ce qui correspond à n’importe quel caractère. Il est possible de modifier ce motif pour personnaliser un peu plus le changement de casse. Attention, dans tous les cas le motif ne doit correspondre qu’à un seul caractère, il n’est par exemple pas possible de faire de la capitalisation via une unique substitution :

USERNAME='zessx'
echo "${USERNAME^^[^aeiouy]}"
# ZeSSX

Suppression de préfixes/suffixes

Les opérateurs # et % permettent respectivement de supprimer un préfixe ou un suffixe :

URL='blog.smarchal.com'
echo "${URL#*.}"
# smarchal.com
URL='https://blog.smarchal.com/'
echo "${URL%/}"
# https://blog.smarchal.com

De la même manière que pour d’autres opérateurs, il existe des versions greedy qui vont supprimer le préfixe/suffixe le plus long correspondant au motif de recherche :

URL='https://blog.smarchal.com'
echo "${URL##*/}"
# blog.marchal.com
URL='blog.smarchal.com/tag/bash/'
echo "${URL%%/*}"
# blog.marchal.com

Substitution de motif

Pour finir, l’opérateur / va vous permettre de remplacer des éléments dans votre variable. En voici la syntaxe complète :

${VARIABLE/MOTIF/CHAINE}

Le motif de recherche est un peu particulier, son premier caractère réutilise les autres opérateurs que nous avons déjà vus afin de modifier le comportement de la substitution :

  • Vide pour remplacer uniquement la première occurrence
  • / pour remplacer toutes les occurrences
  • # pour traiter le motif comme un préfixe
  • % pour traiter le motif comme un suffixe

Les deux derniers ne sont pas forcément très utiles, car vous aurez généralement la possibilité d’obtenir le même résultat avec une substitution de motif simple, ou un autre type de substitution :

URL='http://blog.smarchal.com/tag/http/'
echo "${URL/http/https}"
# https://blog.smarchal.com/tag/http/
FILENAME='Nom de fichier avec des espaces'
echo "${FILENAME// /-}"
# Nom-de-fichier-avec-des-espaces
DATE='2022-03-02'
echo "${DATE//-/}"
# 20220302

Liens

Référence - man bash