Manipuler et/ou étendre les variables
Identique à $parametre, c'est-à-dire la valeur de la variable parametre. Dans certains contextes, seule la forme la moins ambiguë, ${parametre}, fonctionne.
Peut être utilisé pour concaténer des variables avec des suites de caractères (strings).
votre_id=${USER}-sur-${HOSTNAME}
echo "$votre_id"
#
echo "Ancien \$PATH = $PATH"
PATH=${PATH}:/opt/bin #Ajoute /opt/bin à $PATH pour toute la durée du script.
echo "Nouveau \$PATH = $PATH"
Si parametre n'est pas initialisé, utilise defaut.
echo ${nom_utilisateur-`whoami`}
# Affichez le résultat de `whoami`, si la variable $nom_utilisateur n'est
toujours pas initialisée.
${parametre-defaut} et ${parametre:-defaut} sont pratiquement équivalents. Le caractère : supplémentaire fait une différence seulement lorsque parametre a été déclaré mais est nul.
#!/bin/bash
# param-sub.sh
# Qu'une variable ait été déclarée ou non
#+ a un effet sur le déclenchement de l'option par défaut,
#+ y compris si la variable est nulle.
nomutilisateur0=
echo "nomutilisateur0 a été déclaré mais laissé sans valeur."
echo "nomutilisateur0 = ${nomutilisateur0-`whoami`}"
# Rien ne s'affiche.
echo
echo "nomutilisateur1 n'a pas été déclaré."
echo "nomutilisateur1 = ${nomutilisateur1-`whoami`}"
# S'affiche.
nomutilisateur2=
echo "nomutilisateur2 a été déclaré mais laissé sans valeur."
echo "nomutilisateur2 = ${nomutilisateur2:-`whoami`}"
# ^
# S'affiche à cause du :- au lieu du simple - dans le test conditionnel.
# Comparez à la première instance ci-dessus.
#
# Une fois encore :
variable=
# variable a été déclaré mais est initialisé à null.
echo "${variable-0}" # (pas de sortie)
echo "${variable:-1}" # 1
# ^
unset variable
echo "${variable-2}" # 2
echo "${variable:-3}" # 3
exit 0
La construction du paramètre par défaut a pour principale utilité de fournir les arguments « manquants » de la ligne de commande des scripts.
NOM_FICHIER_PAR_DEFAUT=donnees.generiques
nom_fichier=${1:-$NOM_FICHIER_PAR_DEFAUT}
# S'il n'est pas spécifié, l'ensemble de commandes suivantes opère sur le
# fichier "donnees.generiques".
#
# Les commandes suivent.
Voir aussi l'Exemple 3.4, « Sauvegarde de tous les fichiers modifiés dans les dernières 24 heures », l'Exemple 28.2, « Créer un fichier de swap en utilisant /dev/zero » et l'Exemple A.6, « collatz: Séries de Collatz ».
Comparez cette méthode avec l'utilisation d'une liste ET pour fournir un argument par défaut à la ligne de commande.
Si le paramètre n'est pas initialisé, alors initialisation à defaut.
Les deux formes sont pratiquement équivalentes. Le caractère : fait une différence seulement lorsque $parametre a été déclaré et est nul, [28] comme ci-dessus.
echo ${nom_utilisateur=`whoami`}
# La variable "nom_utilisateur" est maintenant initialisée à `whoami`.
Si le paramètre est déclaré, utilisez valeur_alt, sinon utilisez la chaîne de caractères vide.
Les deux formes sont pratiquement équivalentes. Le caractère : fait la différence seulement lorsque parametre a été déclaré nul, voir plus bas.
echo "###### \${parametre+valeur_alt} ########"
echo
a=${param1+xyz}
echo "a = $a" # a =
param2=
a=${param2+xyz}
echo "a = $a" # a = xyz
param3=123
a=${param3+xyz}
echo "a = $a" # a = xyz
echo
echo "###### \${parametre:+valeur_alt} ########"
echo
a=${param4:+xyz}
echo "a = $a" # a =
param5=
a=${param5:+xyz}
echo "a = $a" # a =
# Résultats différents pour a=${param5+xyz}
param6=123
a=${param6:+xyz}
echo "a = $a" # a = xyz
Si le paramètre est initialisé, l'utilise, sinon affiche msg_err.
Les deux formes sont pratiquement équivalentes. Le caractère : fait la différence seulement lorsque parametre a été déclaré nul, comme ci-dessus.
Exemple 9.15. Utiliser la substitution et les messages d'erreur
#!/bin/bash
# Vérifier certaines des variables d'environnements du système.
# C'est une mesure adéquate de maintenance préventive.
# Si, par exemple, $USER, le nom de la personne sur la console, n'est pas
#+ initialisé, la machine ne vous reconnaîtra pas.
: ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?}
echo
echo "Le nom de la machine est $HOSTNAME."
echo "Vous êtes $USER."
echo "Votre répertoire personnel est $HOME."
echo "Votre courrier est situé dans $MAIL."
echo
echo "Si vous lisez ce message, les variables d'environnement "
echo "critiques ont été initialisées."
echo
echo
# ------------------------------------------------------
# La construction ${variablename?} peut aussi vérifier les
#+ variables configurées dans un script.
CetteVariable=Valeur-de-CetteVariable
# Notez que, du coup, les variables chaînes de caractères pourraient être
#+ configurées avec les caractères contenus dans leurs noms.
: ${CetteVariable?}
echo "La valeur de CetteVariable est $CetteVariable".
echo
echo
: ${ZZXy23AB?"ZZXy23AB n'a pas été initialisée."}
# Si ZZXy23AB n'a pas été initialisée, alors le script se termine avec un
#+ message d'erreur.
# Vous pouvez spécifier le message d'erreur.
# : ${nomvariable?"MESSAGE D'ERREUR."}
# Même résultat avec : variable_stupide=${ZZXy23AB?}
# variable_stupide=${ZZXy23AB?"ZXy23AB n'a pas été initialisée."}
#
# echo ${ZZXy23AB?} >/dev/null
# Comparez ces méthodes de vérification sur l'initialisation d'une variable
#+ avec "set -u" ...
echo "Vous ne verrez pas ce message parce que le script s'est déjà terminé"
ICI=0
exit $ICI # Ne sortira *pas* ici.
# En fait, ce script quittera avec un code de sortie 1 (echo $?).
Exemple 9.16. Substitution de paramètres et messages d'« usage »
#!/bin/bash
# usage-message.sh
: ${1?"Usage: $0 ARGUMENT"}
# Le script sort ici si le paramètre en ligne de commande est absent,
#+ avec le message d'erreur suivant.
# usage-message.sh: 1: Usage: usage-message.sh ARGUMENT
echo "Ces deux lignes ne s'affichent que si le paramètre en ligne de commande est donné."
echo "paramètre en ligne de commande = \"$1\""
exit 0 # Sortira ici seulement si le paramètre en ligne de commande est présent.
# Vérifiez le code de sortie, à la fois avec et sans le paramètre en ligne de
#+ commande.
# Si le paramètre en ligne de commande est présent, alors "$?" vaut 0.
# Sinon, "$?" vaut 1.
Substitution de paramètres et/ou expansion. Les expressions suivantes sont le complément des opérations sur les suites de caractères comme match dans expr (voir l'Exemple 15.9, « Utiliser expr »). Ces derniers sont utilisés principalement pour analyser les chemins de fichiers.
Longueur de variables / Suppression d'un sous-ensemble d'une suite de caractères
Longueur de la suite de caractères (ou nombre de caractères dans $var). Pour un tableau, ${#tableau} est la longueur du premier élément dans le tableau.
Exceptions :
${#*} et ${#@} donnent le nombre de paramètres de position.
Pour un tableau, ${#tableau[*]} et ${#tableau[@]} donnent le nombre d'éléments dans le tableau.
Exemple 9.17. Longueur d'une variable
#!/bin/bash
# length.sh
E_SANS_ARGS=65
if [ $# -eq 0 ] # Doit avoir des arguments en ligne de commande.
then
echo "Merci d'appeler ce script avec un ou plusieurs argument(s) en ligne de commande."
exit $E_SANS_ARGS
fi
var01=abcdEFGH28ij
echo "var01 = ${var01}"
echo "Longueur de var01 = ${#var01}"
# Maintenant, essayons d'intégrer un espace.
var02="abcd EFGH28ij"
echo "var02 = ${var02}"
echo "Longueur de var02 = ${#var02}"
echo "Nombre d'arguments en ligne de commande passés au script = ${#@}"
echo "Nombre d'arguments en ligne de commande passés au script = ${#*}"
exit 0
Supprime à partir de $var la plus courte/longue partie de $Modele qui correspond au début de $var.
Un exemple d'usage à partir de l'Exemple A.7, « days-between: Calculer le nombre de jours entre deux dates » :
# Fonction provenant de l'exemple "days-between.sh"
# Supprimer les zéros du début à partir de l'argument donné.
supprimer_les_zeros_du_debut () # Supprime les zéros éventuels au début
{ # à partir des arguments donnés.
return=${1#0} # Le "1 correspond à "$1", argument donné.
# Le "0" correspond à ce qui doit être supprimé de "$1".
}
Une version plus élaborée par Manfred Schwarb :
supprimer_les_zeros_du_debut_2 () # Supprimer les zéros du début, car sinon
{ # Bash interprétera de tels numéros en valeurs octales.
shopt -s extglob # Active le globbing local.
local val=${1##+(0)} # Utilise une variable locale, série correspondante la
# plus longue avec des 0.
shopt -u extglob # Désactive le globbing local.
_strip_leading_zero2=${val:-0}
# Si l'entrée était 0, renvoie 0 au lieu de "".
}
Un autre exemple d'usage :
echo `basename $PWD` # Base du nom du répertoire courant.
echo "${PWD##*/}" # Base du nom du répertoire actuel.
echo
echo `basename $0` # Nom du script.
echo $0 # Nom du script.
echo "${0##*/}" # Nom du script.
echo
filename=test.data
echo "${filename##*.}" # données
# Extension du fichier.
Supprime à partir de $var la partie la plus courte/longue de $Modele qui correspond à la fin de $var.
La version 2 de Bash a ajouté des options supplémentaires.
Exemple 9.18. Correspondance de modèle dans la substitution de paramètres
#!/bin/bash
# patt-matching.sh
# Reconnaissance de modèles en utilisant les opérateurs de substitution # ## % %%
var1=abcd12345abc6789
modele1=a*c # * (joker) recherche tout ce qui se trouve entre a - c.
echo
echo "var1 = $var1" # abcd12345abc6789
echo "var1 = ${var1}" # abcd12345abc6789 (autre forme)
echo "Nombre de caractères dans ${var1} = ${#var1}"
echo
echo "modele1 = $modele1" # a*c (tout entre 'a' et 'c')
echo "------------------"
echo '${var1#$modele1} =' "${var1#$modele1}" # d12345abc6789
# Correspondance la plus petite, supprime les trois premiers caractères de abcd12345abc6789
# ^^^^^^^^ |-|
echo '${var1##$modele1} =' "${var1##$modele1}" # 6789
# Correspondance la plus grande possible, supprime les 12 premiers caractères de abcd12345abc6789
# ^^^^^^^^ |----------|
echo; echo; echo
modele2=b*9 # tout entre 'b' et '9'
echo "var1 = $var1" # Toujours abcd12345abc6789
echo
echo "modele2 = $modele2"
echo "------------------"
echo '${var1%modele2} =' "${var1%$modele2}" # abcd12345a
# Correspondance la plus petite, supprime les six derniers caractères de abcd12345abc6789
# ^^^^^^^^ |----|
echo '${var1%%modele2} =' "${var1%%$modele2}" # a
# Correspondance la plus grande, supprime les douze derniers caractères de abcd12345abc6789
# ^^^^^^^^ |-------------|
# Souvenez-vous, # et ## fonctionnent à partir de la gauche (début) de la chaîne
# % et %% fonctionnent à partir de la droite.
echo
exit 0
Exemple 9.19. Renommer des extensions de fichiers :
#!/bin/bash
# rfe.sh : Renommer les extensions de fichier (Renaming File Extensions).
#
# rfe ancienne_extension nouvelle_extension
#
# Exemple :
# Pour renommer tous les fichiers *.gif d'un répertoire en *.jpg,
# rfe gif jpg
E_MAUVAISARGS=65
case $# in
0|1) # La barre verticale signifie "ou" dans ce contexte.
echo "Usage: `basename $0` ancien_suffixe nouveau_suffixe"
exit $E_MAUVAISARGS # Si 0 ou 1 argument, alors quitter.
;;
esac
for fichier in *.$1
# Traverse la liste des fichiers dont le nom termine avec le premier argument.
do
mv $fichier ${fichier%$1}$2
# Supprime la partie du fichier contenant le premier argument
# puis ajoute le deuxième argument.
done
exit 0
Expansion de variables / Remplacement de sous-chaînes
Ces constructions proviennent de ksh.
La variable var étendue, commençant à la position pos.
Augmentation d'un maximum de len caractères de la variable var, à partir de la position pos. Voir l'Exemple A.14, « password: Générer des mots de passe aléatoires de 8 caractères » pour un exemple d'utilisation particulièrement intéressante de cet opérateur.
Première occurrence de Modele, à l'intérieur de var remplacé par Remplacement.
Si Remplacement est omis, alors la première occurrence de Modele est remplacé par rien, c'est-à-dire qu'il est supprimé.
Remplacement global. Toutes les occurrences de Modele, à l'intérieur de var sont remplacées par Remplacement.
Comme ci-dessus, si Remplacement est omis, alors toutes les occurrences de Modele sont remplacées par rien, c'est-à-dire supprimées.
Exemple 9.20. Utiliser la concordance de modèles pour analyser des chaînes de caractères diverses
#!/bin/bash
var1=abcd-1234-defg
echo "var1 = $var1"
t=${var1#*-*}
echo "var1 (avec tout, jusqu'au et incluant le premier - supprimé) = $t"
# t=${var1#*-} fonctionne de la même façon,
#+ car # correspond à la plus petite chaîne de caractères,
#+ et * correspond à tout ce qui précède, incluant la chaîne vide.
# (Merci, Stéphane Chazelas, pour l'avoir indiqué.)
t=${var1##*-*}
echo "Si var1 contient un \"-\", renvoie une chaîne vide... var1 = $t"
t=${var1%*-*}
echo "var1 (avec tout à partir de la fin - supprimé) = $t"
echo
# -------------------------------------------
nom_chemin=/home/bozo/idees/pensees.pour.aujourdhui
# -------------------------------------------
echo "nom_chemin = $nom_chemin"
t=${nom_chemin##/*/}
echo "nom_chemin, sans les préfixes = $t"
# Même effet que t=`basename $nom_chemin` dans ce cas particulier.
# t=${nom_chemin%/}; t=${t##*/} est une solution plus générale,
#+ mais elle échoue quelques fois.
# Si $nom_chemin finit avec un retour chariot, alors `basename $nom_chemin`
#+ ne fonctionnera pas mais l'expression ci-dessus le fera.
# (Merci, S.C.)
t=${nom_chemin%/*.*}
# Même effet que t=`dirname $nom_chemin`
echo "nom_chemin, sans les suffixes = $t"
# Ceci va échouer dans certains cas, comme "../", "/foo////", # "foo/", "/".
# Supprimer les suffixes, spécialement quand le nom de base n'en a pas, mais
#+ que le nom du répertoire en a un, complique aussi le problème.
# (Merci, S.C.)
echo
t=${nom_chemin:11}
echo "$nom_chemin, avec les 11 premiers caractères supprimés = $t"
t=${nom_chemin:11:5}
echo "$nom_chemin, avec les 11 premiers caractères supprimés, longueur 5 = $t"
echo
t=${nom_chemin/bozo/clown}
echo "$nom_chemin avec \"bozo\" remplacé par \"clown\" = $t"
t=${nom_chemin/today/}
echo "$nom_chemin avec \"today\" supprimé = $t"
t=${nom_chemin//o/O}
echo "$nom_chemin avec tous les o en majuscule = $t"
t=${nom_chemin//o/}
echo "$nom_chemin avec tous les o supprimés = $t"
exit 0
Si le préfixe de var correspond à Modele, alors Remplacement remplace Modele.
Si le suffixe de var correspond à Modele, alors Remplacement remplace Modele.
Exemple 9.21. Modèles correspondant au préfixe ou au suffixe d'une chaîne de caractères
#!/bin/bash
# varmatch.sh
# Démonstration de remplacement de modèle sur le préfixe / suffixe d'une chaîne de
#+ caractères.
v0=abc1234zip1234abc # Variable originale.
echo "v0 = $v0" # abc1234zip1234abc
echo
# Correspond au préfixe (début) d'une chaîne de caractères.
v1=${v0/#abc/ABCDEF} # abc1234zip1234abc
# |-|
echo "v1 = $v1" # ABCDEF1234zip1234abc
# |----|
# Correspond au suffixe (fin) d'une chaîne de caractères.
v2=${v0/%abc/ABCDEF} # abc1234zip1234abc
# |-|
echo "v2 = $v2" # abc1234zip1234ABCDEF
# |----|
echo
# ----------------------------------------------------
# Doit correspondre au début / fin d'une chaîne de caractères.
# sinon aucun remplacement ne se fera.
# ----------------------------------------------------
v3=${v0/#123/000} # Correspond, mais pas au début.
echo "v3 = $v3" # abc1234zip1234abc
# PAS DE REMPLACEMENT.
v4=${v0/%123/000} # Correspond, mais pas à la fin.
echo "v4 = $v4" # abc1234zip1234abc
# PAS DE REMPLACEMENT.
exit 0
Correspond à toutes les variables déjà déclarées commençant par varprefixe.
xyz23=quoiquecesoit
xyz24=
a=${!xyz*} # Se développe en les noms des variables précédemment déclarées
# commençant par "xyz".
echo "a = $a" # a = xyz23 xyz24
a=${!xyz@} # Même chose que ci-dessus.
echo "a = $a" # a = xyz23 xyz24
# Bash, version 2.04, ajoute cette fonctionnalité.
[28] Si $parametre est nul dans un script non interactif, il se terminera avec un code de retour 127 (le code d'erreur de Bash pour « commande introuvable »).