4.4. Types de variables spéciales

variables locales

variables visibles uniquement à 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 trop d'espace excessif peut créer des ennuis.

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é son parent.

paramètres de position

Ce sont les arguments passés aux scripts depuis la ligne de commande [23] : $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. [24] 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

&ex17;

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}
# Note: Ceci est une *référence indirecte* à $args ...

# Ou :      dernierarg=${!#}           (Merci à Chris Monson)
# Ceci est une *référence indirecte* à la variable $#.
# Notez que dernierarg=${!$#} 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 vide, 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

&ex18;

---

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

&ex19;

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

#  Néanmoins, comme Eleni Fragkiadaki l'indique,
#+ tenter un 'shift' après le nombre de paramètres de position
#+ ($#) renvoie un code de sortie de 1, et les paramètres de
#+ position ne changent pas.
#  Cela signifie qu'il est possible d'aboutir à une boucle sans fin...
#  Par exemple :
#      until [ -z "$1" ]
#      do
#         echo -n "$1 "
#         shift 20    #  Si moins de 20 paramètres de position,
#      done           #+ la boucle ne termine jamais !
#
# En cas de doute, ajoutez une vérification...
#           shift 20 || break
#                    ^^^^^^^^
[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.16, « Astuce de valeur de retour ».



[24] Le processus qui appelle le script affecte le paramètre $0. Par convention, ce paramètre est le nom du script. Voir la page de manuel d'execv.

Cependant, en ligne de commande, $0 est le nom du shell.

bash$ echo $0
bash

tcsh% echo $0
tcsh