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 la durée du script. echo "Nouveau \$PATH = $PATH"
var1=1 var2=2 # var3 n'est pas initialisée. echo ${var1-$var2} # 1 echo ${var3-$var2} # 2 ^ Remarquez le préfixe $. echo ${nom_utilisateur-`whoami`} # Affiche le résultat de `whoami` si la variable $nom_utilisateur n'est #+ pas encore initialisée.
#!/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 avec le premier exemple ci-dessus. # # Je répète : variable= # variable a été déclarée mais est initialisée à null. echo "${variable-0}" # (pas de sortie) echo "${variable:-1}" # 1 # ^ unset variable echo "${variable-2}" # 2 echo "${variable:-3}" # 3 exit 0
Cette syntaxe de paramètre par défaut sert notamment, dans les scripts, à renseigner les arguments « absents » de la ligne de commande.
NOM_FICHIER_PAR_DEFAUT=donnees.generiques nom_fichier=${1:-$NOM_FICHIER_PAR_DEFAUT} # Si rien n'est spécifié, l'ensemble de commandes suivant opère sur le #+ fichier "donnees.generiques". # Debut-Bloc-Commandes # ... # ... # ... # Fin-Bloc-Commandes # Exemple tiré de "hanoi2.bash" : DISQUES=${1:-E_NOPARAM} # Il faut préciser le nombre de disques # Affecter la valeur $1 (le paramètre de ligne de commande) à #+ $DISQUES, ou $E_NOPARAM si $1 n'est pas #+ initialisée.
Voir aussi l'Exemple 3.4, « Sauvegarde de tous les fichiers modifiés depuis 24 heures », l'Exemple 31.2, « Créer un fichier de swap en utilisant /dev/zero » et l'Exemple A.6, « 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 à la valeur par défaut.
Les deux formes sont pratiquement équivalentes. Le caractère : fait une différence seulement lorsque $parametre a été déclaré nul, [50] comme ci-dessus.
echo ${var=abc} # abc echo ${var=xyz} # abc # $var avait déjà été initialisée à abc, donc pas de changement.
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 ci-dessous.
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ésultat différent de a=${param5+xyz} param6=123 a=${param6:+xyz} echo "a = $a" # a = xyz
Si le paramètre est initialisé, l'utiliser, sinon afficher msg_err et interrompre le script avec un code de sortie de 1.
Ces deux formes sont pratiquement équivalentes. Le caractère : fait la différence seulement lorsque parametre a été déclaré nul, comme ci-dessus.
Exemple 10.7. Utiliser le remplacement 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 # ------------------------------------------------------ # L'expression ${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 10.8. Remplacement 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 un paramètre en ligne de commande est donné." echo "paramètre en ligne de commande = \"$1\"" exit 0 # Sortira ici seulement si un paramètre en ligne de commande est présent. # Vérifiez le code de sortie, avec ou sans paramètre en ligne de #+ commande. # Si un paramètre en ligne de commande est présent, alors "$?" vaut 0. # Sinon, "$?" vaut 1.
Remplacement, expansion de paramètres. Les expressions suivantes sont le complément des opérations sur les suites de caractères comme match dans expr (voir l'Exemple 16.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.
Exemple 10.9. 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
${var#Motif} Supprime de $var la partie la plus courte de $Motif correspondant au début de $var.
${var##Motif} Supprime de $var la partie la plus longue de $Motif correspondant au début de $var.
Un exemple d'utilisation à 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 le(s) zéro(s) du début à partir de l'argument donné. supprimer_les_zeros_du_debut () # Supprime les zéros éventuels du début { # à partir des arguments donnés. return=${1#0} # Le "1" correspond à "$1", argument fourni. # 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 et fait correspondre la # suite de zéros la plus longue. shopt -u extglob # Désactive le globbing local. _strip_leading_zero2=${val:-0} # Si l'entrée était 0, renvoie 0 au lieu de "". }
Autre exemple d'utilisation :
echo `basename $PWD` # Base du nom du répertoire courant. echo "${PWD##*/}" # Nom de base du répertoire de travail. echo echo `basename $0` # Nom du script. echo $0 # Nom du script. echo "${0##*/}" # Nom du script. echo filename=test.data echo "${filename##*.}" # data # Extension du fichier.
${var%Motif} Supprime de $var la partie la plus courte de $Motif qui s'ajuste à la fin de $var.
${var%%Motif} Supprime de $var la partie la plus longue de $Motif qui s'ajuste à la fin de $var.
Dans la version 2 de Bash, on a ajouté des options supplémentaires.
Exemple 10.10. Correspondance de motifs dans le remplacement de paramètres
#!/bin/bash # patt-matching.sh # Reconnaissance de motifs avec les opérateurs de substitution # ## % %% var1=abcd12345abc6789 motif1=a*c # * (joker) recherche tout ce qui se trouve entre a et c. echo echo "var1 = $var1" # abcd12345abc6789 echo "var1 = ${var1}" # abcd12345abc6789 (autre forme) echo "Nombre de caractères dans ${var1} = ${#var1}" echo echo "motif1 = $motif1" # a*c (tout entre 'a' et 'c') echo "------------------" echo '${var1#$motif1} =' "${var1#$motif1}" # d12345abc6789 # Correspondance la plus petite, supprime les trois premiers caractères de abcd12345abc6789 # ^^^^^^^^ |-| echo '${var1##$motif1} =' "${var1##$motif1}" # 6789 # Correspondance la plus grande possible, supprime les 12 premiers caractères de abcd12345abc6789 # ^^^^^^^^ |----------| echo; echo; echo motif2=b*9 # tout entre 'b' et '9' echo "var1 = $var1" # Toujours abcd12345abc6789 echo echo "motif2 = $motif2" echo "------------------" echo '${var1%motif2} =' "${var1%$motif2}" # abcd12345a # Correspondance la plus petite, supprime les six derniers caractères de abcd12345abc6789 # ^^^^^^^^ |----| echo '${var1%%motif2} =' "${var1%%$motif2}" # a # Correspondance la plus grande, supprime les quinze 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 10.11. Renommer des extensions de fichiers :
#!/bin/bash # rfe.sh : Renommer des 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
Remplacement de variables / Remplacement de sous-chaînes
Ce type de syntaxe vient de ksh.
La variable var remplacée par sa valeur, prise à partir de la position pos.
Remplacement de la variable var par sa valeur, prise à partir de la position pos et sur au plus len caractères. Voir l'Exemple A.13, « password: Générer des mots de passe aléatoires de 8 caractères » pour un exemple d'utilisation particulièrement intéressant de cet opérateur.
Première occurrence de Motif, à l'intérieur de var remplacé par Remplacement.
Si Remplacement est omis, alors la première occurrence de Motif est remplacée par rien, c'est-à-dire supprimée.
Remplacement global. Toutes les occurrences de Motif, à l'intérieur de var sont remplacées par Remplacement.
Comme ci-dessus, si Remplacement est omis, alors toutes les occurrences de Motif sont remplacées par rien, c'est-à-dire supprimées.
Exemple 10.12. Utilisation de la concordance de motifs pour analyser diverses chaînes de caractères
#!/bin/bash var1=abcd-1234-defg echo "var1 = $var1" t=${var1#*-*} echo "var1 (on supprime tout ce qui se trouve jusqu'au premier -, y compris ce -) = $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, même la chaîne vide. # (Merci, Stéphane Chazelas, pour cette indication.) t=${var1##*-*} echo "Si var1 contient un \"-\", renvoie une chaîne vide... var1 = $t" t=${var1%*-*} echo "var1 (on supprime tout à partir du dernier -) = $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 en moins = $t" t=${nom_chemin:11:5} echo "$nom_chemin, avec les 11 premiers caractères en moins et sur 5 caractères = $t" echo t=${nom_chemin/bozo/clown} echo "$nom_chemin avec \"bozo\" remplacé par \"clown\" = $t" t=${nom_chemin/aujourdhui/} echo "$nom_chemin avec \"aujourdhui\" supprimé = $t" t=${nom_chemin//o/O} echo "$nom_chemin avec tous les o en majuscules = $t" t=${nom_chemin//o/} echo "$nom_chemin avec tous les o en moins = $t" exit 0
Si le préfixe de var est conforme à Motif, alors Motif est remplacé par Remplacement.
Si le suffixe de var est conforme à Motif, alors Motif est remplacé par Remplacement.
Exemple 10.13. Motifs se conformant au préfixe ou au suffixe d'une chaîne de caractères
#!/bin/bash # varmatch.sh # Démonstration de remplacement de motif sur le préfixe ou suffixe d'une chaîne de #+ caractères. v0=abc1234zip1234abc # Variable de départ. 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
Établit une correspondance des noms de toutes les variables déjà déclarées commençant par debutvar.
# Voici une variation sur la référence #+ indirecte, mais avec un * ou un @. # Cette fonctionnalité a été ajoutée dans la version 2.04 de Bash. xyz23=quelquechose xyz24= a=${!xyz*} # Se développe en les *noms* des variables déclarées précédemment # ^ ^ ^ #+ et commençant par "xyz". echo "a = $a" # a = xyz23 xyz24 a=${!xyz@} # Même chose que ci-dessus. echo "a = $a" # a = xyz23 xyz24 echo "---" abc23=autrechose b=${!abc*} echo "b = $b" # b = abc23 c=${!b} # à présent, une référence indirecte d'un genre plus familier echo $c # autrechose
[50] Si $parametre est nul dans un script non interactif, il se terminera avec le code de retour 127 (code d'erreur de Bash pour « commande introuvable »).