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 rc
guscio e suoi derivati come es
e akanga
supportano 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
, yash
e 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 zsh
o ksh
pensare 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).
ksh93
ha 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 zsh
ha problemi con il suo $path
o $commands
variabili 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 ( bash
rimuove quello con un nome vuoto, ash
, ksh
e bash
rimuovere 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
, csh
e tcsh
su Linux amd64, ma non con una qualsiasi delle altre shell che ho provato ( mksh
, ksh93
, bash
, dash
)).