Podczas gdy zmienne środowiskowe mogą mieć dowolną nazwę (w tym pusty ciąg znaków) niezawierającą znaku równości lub bajtu zerowego, powłoki odwzorowują zmienne środowiskowe na zmienne powłoki, aw większości powłok nazwy zmiennych są ograniczone do znaków alfanumerycznych ASCII i _
gdzie pierwszy znak może „ t być cyfra (z wyjątkiem parametrów pozycyjnych i innych specjalnych, takich jak te $*
, $-
, $@
, ..., (które nie są przypisane do odpowiednich zmiennych środowiskowych)). Zauważ też, że niektóre zmienne są zarezerwowane / specjalne przez / dla powłoki.
Wyjątki od tego:
rc
Powłoki i jej pochodne, jak es
i akanga
wesprzeć dowolną nazwę, z wyjątkiem ciąg pusty, a te, które są all-numeryczny lub zawierać =
znaków (i zawsze wyeksportować wszystkie swoje zmienne środowiska, a strzeżcie zmiennych specjalnych podoba *
, status
, pid
...):
; '%$£"' = test
; echo $'%$£"'
test
; '' = x
zero-length variable name
;
Jednak używa własnego kodowania dla zmiennych, których nazwa nie zawiera alnums lub tablic, gdy są przekazywane w środowisku wykonywanych poleceń:
$ 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
a zsh
(również bash
ale tylko dla znaków jednobajtowych) alnums wsparcia w bieżącej lokalizacji, a nie tylko te, które ASCII.
$ Stéphane=1
$ echo "$Stéphane"
1
W tych powłokach można zmienić ustawienia regionalne, aby większość znaków traktować jako alfa, ale nadal nie działałoby to w przypadku znaków ASCII, takich jak .
. Możesz oszukiwać zsh
lub ksh
myśleć, że £
to litera, ale nie ta .
lub jakikolwiek inny znak ASCII (w przypadku dopuszczenia znaków w nazwach zmiennych, nie [[:alpha:]]
na przykład dla globu).
ksh93
ma specjalne zmienne, których nazwa zawiera kropkę ${.sh.version}
, ale nie są odwzorowane na zmienne środowiskowe i są wyjątkowe. Ma .
to na celu upewnienie się, że nie powoduje konfliktu z innymi zmiennymi. Gdyby zdecydował się go wywołać $sh_version
, mógłby mieć potencjalnie uszkodzone skrypty, które już używały tej zmiennej (zobacz na przykład, w jaki sposób występują zsh
problemy z jej $path
lub $commands
specjalnymi zmiennymi tablicowymi / mieszającymi (a la csh), które psują niektóre skrypty).
Należy pamiętać, że oprócz muszli nie wspierających takie zmienne, jak niektóre powłoki pdksh / mksh uwagi usunąć je z otoczenia, które otrzymują ( bash
usuwa jedną z pustą nazwą ash
, ksh
a bash
usunąć te ciągi środowiskowe, które nie zawierają =
znaków):
$ 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 %%%
%%%
Podsumowując, najlepiej jest trzymać się nazw zmiennych obsługiwanych przez większość muszli, a nawet próbować używać dużych liter dla zmiennych środowiskowych (i małe litery lub mieszane przypadku nie wywiezionych zmiennych powłoki) unikanie tych, które są wyjątkowe w muszli (jak IFS
, PS1
, BASH_VERSION
...)
Jeśli musisz ustawić taką zmienną w powłoce, która ich nie obsługuje, ale ich nie odrzuca, możesz albo sam wykonać ponownie, używając czegoś takiego:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(oczywiście, jeśli musisz to zrobić w środku skryptu, to nie pomoże, ale możesz rzucić okiem na to podejście do zapisywania i przywracania środowiska wykonywania powłoki po ponownym wykonaniu). Lub wypróbuj metodę debuggera:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(to zdaje się pracy z zsh
, yash
, csh
i tcsh
na Linux amd64, ale nie z żadnym z innych skorup próbowałem ( mksh
, ksh93
, bash
, dash
)).