Alors que les variables d'environnement peuvent avoir n'importe quel nom (y compris la chaîne vide) ne contenant ni signe égal ni octet nul, les shells mappent les variables d'environnement à des variables shell et, dans la plupart des shells, les noms de variables sont limités aux caractères alphanumériques ASCII _
. t un chiffre (sauf pour les paramètres de position et d' autres comme ceux spéciaux $*
, $-
, $@
, ..., (qui ne sont pas mis en correspondance avec les variables d'environnement correspondantes)). Notez également que certaines variables sont réservées / spéciales par / au shell.
Les exceptions à cela:
La rc
coquille et ses dérivés comme es
et akanga
prennent en charge un nom , sauf la chaîne vide, et ceux qui sont tout numérique ou contiennent des =
caractères (et toujours exporter toutes leurs variables à l'environnement, et méfiez - vous des variables spéciales comme *
, status
, pid
...):
; '%$£"' = test
; echo $'%$£"'
test
; '' = x
zero-length variable name
;
Cependant, il utilise son propre codage pour les variables dont le nom ne contient pas d'alnums ou pour les tableaux lorsqu'il est passé dans l'environnement des commandes en cours d'exécution:
$ rc -c '+ = zzz; __ = zzz; a = (zzz xxx); env' | sed -n /zzz/l
__2b=zzz$
__5f_=zzz$
a=zzz\001xxx$
$ env +=x rc -c "echo $'+'"
x
$ env __2b=x rc -c "echo $'+'"
x
AT & T ksh
, yash
et zsh
(également bash
mais uniquement pour les caractères à octet unique), prennent en charge les alnums dans les paramètres régionaux actuels, pas seulement ceux en ASCII.
$ Stéphane=1
$ echo "$Stéphane"
1
Dans ces shells, vous pouvez modifier les paramètres régionaux pour considérer la plupart des caractères comme des caractères alpha, mais cela ne fonctionnerait pas pour les caractères ASCII tels que .
. Vous pouvez tromper zsh
ou ksh
penser que £
c'est une lettre, mais pas cela .
ni aucun autre caractère ASCII (où autoriser les caractères dans les noms de variables est concerné, pas pour le [[:alpha:]]
glob par exemple).
ksh93
a des variables spéciales dont le nom contient un point comme ${.sh.version}
, mais celles-ci ne sont pas mappées à des variables d'environnement et sont spéciales. Le .
est de s'assurer qu'il ne soit pas en conflit avec d'autres variables. Si elle avait choisi de l' appeler $sh_version
, il aurait pu les scripts potentiellement cassés qui a utilisé cette variable déjà (voir par exemple comment zsh
a des problèmes avec son $path
ou des $commands
variables tableau spécial / hachage (à la csh) qui brisent certains scripts).
Notez que , en plus de coquilles qui ne supportent pas ces variables, des coquilles comme pdksh / mksh font supprimer les de l'environnement qu'ils reçoivent ( bash
supprime l'un avec un nom vide, ash
, ksh
et bash
supprimer les chaînes d'environnement qui ne contiennent pas de =
caractère):
$ env %%%=test 1=%%% a.b=%%% mksh -c env | grep %%%
$ env %%%=test 1=%%% a.b=%%% bash -c env | grep %%%
%%%=test
a.b=%%%
1=%%%
$ perl -le '$ENV{""}="%%%"; exec "bash", "-c", "env"' | grep %%%
$ perl -le '$ENV{""}="%%%"; exec "zsh", "-c", "env"' | grep %%%
=%%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
execve("/bin/ash",a,e);}'|tcc -run - | grep %%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
execve("/bin/zsh",a,e);}'|tcc -run - | grep %%%
%%%
En résumé, le mieux est de coller avec les noms de variables pris en charge par la plupart des coquilles et même essayer d'utiliser les majuscules pour les variables d'environnement (et minuscules ou majuscules et minuscules pour les variables shell non exportées) en évitant ceux qui sont spéciaux dans des coquilles (comme IFS
, PS1
, BASH_VERSION
...)
Si vous devez définir une telle variable dans un shell qui ne la prend pas en charge, mais ne la supprime pas, vous pouvez soit réexécuter vous-même, avec quelque chose comme:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(Évidemment, si vous devez le faire au milieu du script, cela ne vous aidera pas, mais vous pourrez alors examiner cette approche pour enregistrer et restaurer l'environnement d'exécution du shell sur une nouvelle exécution). Ou essayez l'approche du débogueur:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(que l' on semble travailler avec zsh
, yash
, csh
et tcsh
sur Linux AMD64, mais pas avec l' une des autres coquilles que j'ai essayé ( mksh
, ksh93
, bash
, dash
)).