4.4. Types spéciaux de variables

variables locales

variables visibles seulement à l'intérieur d'un bloc de code ou d'une fonction (voir aussi variables locales dans fonctions)

variables d'environnement

variables qui affectent le comportement du shell et de l'interface utilisateur

[Note]

Note

Dans un contexte plus général, chaque processus a un « environnement », c'est-à-dire un groupe de variables contenant des informations auxquelles pourrait faire référence le processus. En ce sens, le shell se comporte comme n'importe quel processus.

Chaque fois qu'un shell démarre, il crée les variables shell correspondantes à ses propres variables d'environnement. Mettre à jour ou ajouter de nouvelles variables d'environnement force le shell à mettre à jour son environnement, et tous les processus fils (les commandes qu'il exécute) héritent de cet environnement.

[Attention]

Attention

L'espace alloué à l'environnement est limité. Créer trop de variables d'environnement ou une variable d'environnement qui utilise un espace excessif peut causer des problèmes.

bash$ eval "`seq 10000 | sed -e 's/.*/export var&=ZZZZZZZZZZZZZZ/'`"

bash$ du
bash: /usr/bin/du: Argument list too long
                  

(Merci à Stéphane Chazelas pour la clarification et pour avoir fourni l'exemple ci-dessus.)

Si un script déclare des variables d'environnement, il faut qu'elles soient « exportées », c'est-à-dire, rapportées à l'environnement local du script. C'est la fonction de la commande export .

[Note]

Note

Un script peut exporter des variables seulement aux processus fils, c'est-à-dire seulement aux commandes ou processus que ce script particulier initie. Un script invoqué depuis la ligne de commande ne peut pas ré-exporter des variables à destination de l'environnement de la ligne de commande dont il est issu. Des processus fils ne peuvent pas réexporter de variables aux processus parents qui les ont fait naître.

Définition : un processus enfant est un sous-processus lancé par un autre processus appelé parent.

---

paramètres positionnels

Ce sont les arguments passés aux scripts depuis la ligne de commande - $0, $1, $2, $3...

$0 est le nom du script lui-même, $1 est le premier argument, $2 le second, $3 le troisième, et ainsi de suite. [19] Après $9, les arguments doivent être entourés d'accolades, par exemple ${10}, ${11}, ${12}.

Les variables spéciales $* et $@ représentent tous les paramètres positionnels.

Exemple 4.5. Paramètres positionnels

#!/bin/bash

# Appelez ce script avec au moins 10 paramètres, par exemple
# ./nom_script 1 2 3 4 5 6 7 8 9 10
MINPARAMS=10

echo

echo "Le nom de ce script est \"$0\"."
# Ajoutez ./ pour le répertoire courant.
echo "Le nom de ce script est \"`basename $0`\"."
# Supprime le chemin du script (voir 'basename')

echo

if [ -n "$1" ]              # La variable testée est entre guillemets.
then
 echo "Le paramètre #1 est $1"  # Nous avons besoin des guillemets pour échapper #
fi 

if [ -n "$2" ]
then
 echo "Le paramètre #2 est $2"
fi 

if [ -n "$3" ]
then
 echo "Le paramètre #3 est $3"
fi 

# ...


if [ -n "${10}" ]  #  Les paramètres supérieures à $9 doivent être compris entre
                   #+ accolades.
then
 echo "Le paramètre #10 est ${10}"
fi 

echo "-----------------------------------"
echo "Tous les paramètres de la ligne de commande sont: "$*""

if [ $# -lt "$MINPARAMS" ]
then
  echo
  echo "Ce script a besoin d'au moins $MINPARAMS arguments en ligne de commande!"
fi  

echo

exit 0

La notation avec accolades pour les paramètres positionnels permet de référencer plutôt simplement le dernier argument passé à un script sur la ligne de commande. Ceci requiert également le référencement indirect.

args=$#           # Nombre d'arguments passés.
dernarg=${!args}
# Ou :      dernarg=${!#}
#           (Merci à Chris Monson)
# Notez que dernarg=${!$#} ne fonctionne pas.

Certains scripts peuvent effectuer différentes opérations suivant le nom sous lequel ils sont invoqués. Pour que cela fonctionne, le script a besoin de tester $0, le nom sous lequel il a été invoqué. Il doit aussi y avoir des liens symboliques vers tous les différents noms du script. Voir l'Exemple 15.2, « Hello or Good-bye ».

[Astuce]

Astuce

Si un script attend un paramètre en ligne de commande mais qu'il est invoqué sans, cela peut causer une affectation à valeur nulle, généralement un résultat non désiré. Une façon d'empêcher cela est d'ajouter un caractère supplémentaire des deux côtés de l'instruction d'affectation utilisant le paramètre positionnel attendu.

variable1_=$1_ # Plutôt que variable1_=$1
# Cela préviendra l'erreur, même si le paramètre positionnel est absent.

argument_critique01=$variable1_

# Le caractère supplémentaire peut être retiré plus tard comme ceci.
variable1=${variable1_/_/}
# Il n'y aura d'effets de bord que si $variable1_ commence par un tiret bas.
# Ceci utilise un des patrons de substitution de paramètres discutés plus tard
# (laisser vide le motif de remplacement aboutit à une destruction).

# Une façon plus directe de résoudre ce problème est de simplement tester
#+ si le paramètre postionnel attendu a bien été passé.
if [ -z $1 ]
then
  exit $E_PARAM_POS_MANQUANT
fi


#  Néanmoins, comme l'indique Fabian Kreutz,
#+ la méthode ci-dessus pourrait avoir des effets de bord.
#  Une meilleure méthode est la substitution de paramètres :
#         ${1:-$DefaultVal}
#  Voir la section « Substitution de paramètres »
#+ dans le chapitre « Les variables revisitées ».

---

Exemple 4.6. wh, recherche d'un nom de domaine avec whois

#!/bin/bash
# ex18.sh

# Fait une recherche 'whois nom-domaine' sur l'un des trois serveurs:
#                    ripe.net, cw.net, radb.net

# Placez ce script -- renommé 'wh' -- dans /usr/local/bin

# Requiert les liens symboliques :
# ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe
# ln -s /usr/local/bin/wh /usr/local/bin/wh-cw
# ln -s /usr/local/bin/wh /usr/local/bin/wh-radb

E_SANSARGS=65

if [ -z "$1" ]
then
  echo "Usage: `basename $0` [nom-domaine]"
  exit $E_SANSARGS
fi

# Vérifie le nom du script et appelle le bon serveur
case `basename $0` in # Ou :    case ${0##*/} in
    "wh"     ) whois $1@whois.ripe.net;;
    "wh-ripe") whois $1@whois.ripe.net;;
    "wh-radb") whois $1@whois.radb.net;;
    "wh-cw"  ) whois $1@whois.cw.net;;
    *        ) echo "Usage: `basename $0` [nom-domaine]";;
esac 

exit $?

---

La commande shift réassigne les paramètres positionnels, ce qui a le même effet que de les déplacer vers la gauche d'un rang.

$1 <--- $2, $2 <--- $3, $3 <--- $4, etc.

Le vieux $1 disparaît mais $0 (le nom du script) ne change pas. Si vous faites usage d'un grand nombre de paramètres positionnels dans un script, shift vous permet d'accèder à ceux au-delà de 10, bien que la notation {accolades} le permette également.

Exemple 4.7. Utiliser shift

#!/bin/bash
# shft.sh : Utilisation de 'shift' pour voir tous les paramètres de position.

#  Nommez ce script quelque chose comme shft.sh,
#+ et exécutez-le avec quelques paramètres.
#+ Par exemple :
#          sh shft.sh a b c def 23 skidoo

until [ -z "$1" ]  # Jusqu'à ne plus avoir de paramètres...
do
  echo -n "$1 "
  shift
done

echo               # Retour chariot supplémentaire.

exit 0

#  Voir aussi le script echo-params.sh
#+ pour une méthode n'utilisant pas shift pour passer de paramètre en paramètre.

La commande shift peut prendre un paramètre numérique indiquant le nombre de décalages.

#!/bin/bash
# shift-past.sh

shift 3    # Décale de 3 positions.
#  n=3; shift $n
#  a le même effet.

echo "$1"

exit 0


$ sh shift-past.sh 1 2 3 4 5
4
[Note]

Note

La commande shift fonctionne d'une façon similaire à la façon de passer des paramètres à une fonction. Voir l'Exemple 33.15, « Astuce de valeur de retour ».



[19] Le processus appelant le script affecte le paramètre $0. Par convention, ce paramètre est le nom du script. Voir la page man d'execv.