Mentre le variabili di ambiente possono avere qualsiasi nome (inclusa la stringa vuota) che non contenga un segno uguale o un byte null, le shell associano le variabili di ambiente alle variabili di shell e nella maggior parte delle shell, i nomi delle variabili sono limitati ai caratteri alfanumerici ASCII e _dove il primo carattere può " t essere una cifra (esclusi i parametri posizionali e altri quelli speciali come $*, $-, $@, ..., (che non vengono mappati ai corrispondenti variabili di ambiente)). Si noti inoltre che alcune variabili sono riservate / speciali da / alla shell.
Eccezioni a ciò:
Il rcguscio e suoi derivati come ese akangasupportano qualsiasi nome eccetto la stringa vuota, e quelli che sono del tutto-numerico o contengono =caratteri (e sempre esportare tutti loro variabili per l'ambiente, e l'azione del variabili speciali come *, status, pid...):
; '%$£"' = test
; echo $'%$£"'
test
; '' = x
zero-length variable name
;
Tuttavia, utilizza la propria codifica per le variabili il cui nome non contiene alnum o per array quando passato nell'ambiente dei comandi in esecuzione:
$ 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, yashe zsh(anche bash, ma solo per i caratteri a un byte) alnums supporto nella localizzazione corrente, non solo quelli ASCII.
$ Stéphane=1
$ echo "$Stéphane"
1
In quelle shell, potresti cambiare le impostazioni locali per considerare la maggior parte dei caratteri come alfa, ma ciò non funzionerebbe con caratteri ASCII come .. Puoi ingannare zsho kshpensare che £è una lettera, ma non quello .o qualsiasi altro carattere ASCII (per quanto riguarda consentire i caratteri nei nomi delle variabili, non per il [[:alpha:]]glob per esempio).
ksh93ha variabili speciali il cui nome contiene un punto simile ${.sh.version}, ma quelle non sono mappate su variabili di ambiente e sono speciali. Lo scopo .è assicurarsi che non sia in conflitto con altre variabili. Se avesse scelto di chiamarlo $sh_version, allora avrebbe potuto potenzialmente rotto script che ha utilizzato quella variabile già (si veda ad esempio quanto zshha problemi con il suo $patho $commandsvariabili speciali matrice / hash (alla csh) che si rompono alcuni script).
Si noti che, oltre a conchiglie che non supportano tali variabili, alcune conchiglie come pdksh / mksh fanno togliere loro dall'ambiente che ricevono ( bashrimuove quello con un nome vuoto, ash, kshe bashrimuovere quelle stringhe di ambiente che non contengono un =carattere):
$ 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 %%%
%%%
Per riassumere, migliore è attaccare con nomi variabili supportati dalla maggior parte dei gusci e anche cercare di utilizzare maiuscole per le variabili di ambiente (e minuscole o miste per variabili shell non-esportati) evitando quelle che sono speciali in conchiglie (come IFS, PS1, BASH_VERSION...).
Se hai bisogno di impostare una tale variabile in una shell che non le supporta, ma non le scarta, puoi rieseguire te stesso, con qualcosa del tipo:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(ovviamente, se è necessario farlo nel mezzo dello script, ciò non sarà di aiuto, ma si potrebbe quindi dare un'occhiata a quell'approccio per salvare e ripristinare l'ambiente di esecuzione della shell su un re-exec). Oppure prova l'approccio debugger:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(che sembra di lavoro con zsh, yash, cshe tcshsu Linux amd64, ma non con una qualsiasi delle altre shell che ho provato ( mksh, ksh93, bash, dash)).