Embora as variáveis de ambiente possam ter qualquer nome (incluindo a cadeia vazia) que não contenha um sinal de igual ou um byte nulo, os shells mapeiam variáveis de ambiente para variáveis de shell e, na maioria dos shells, os nomes de variáveis são limitados a caracteres alfanuméricos ASCII e _
onde o primeiro caractere pode ' t ser um dígito (exceto para os parâmetros posicionais e outras especiais, como $*
, $-
, $@
, ..., (que não são mapeados para as variáveis de ambiente correspondentes)). Observe também que algumas variáveis são reservadas / especiais por / para o shell.
Exceções a isso:
O rc
shell e seus derivados, como es
e akanga
apoiar qualquer nome, exceto a cadeia vazia, e aqueles que são todos-numérico ou conter =
caracteres (e sempre exportar todas as suas variáveis para o meio ambiente, e cuidado com variáveis especiais como *
, status
, pid
...):
; '%$£"' = test
; echo $'%$£"'
test
; '' = x
zero-length variable name
;
No entanto, ele usa sua própria codificação para variáveis cujo nome não contém alnums ou para matrizes quando passadas no ambiente de comandos sendo executados:
$ 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
(também bash
mas apenas para caracteres de byte único) alnums de apoio na localidade atual, não únicos ASCII.
$ Stéphane=1
$ echo "$Stéphane"
1
Nessas shells, você pode alterar o código do idioma para considerar a maioria dos caracteres como alfa, mas ainda assim não funcionaria para caracteres ASCII .
. Você pode enganar zsh
ou ksh
pensar que £
é uma letra, mas não esse .
ou qualquer outro caractere ASCII (no caso de permitir caracteres em nomes de variáveis, não para a [[:alpha:]]
glob, por exemplo).
ksh93
possui variáveis especiais cujo nome contém um ponto como ${.sh.version}
, mas não são mapeadas para variáveis de ambiente e são especiais. O .
é para garantir que não entre em conflito com outras variáveis. Se tivesse escolhido para chamá-lo $sh_version
, então ele poderia ter potencialmente roteiros quebrado que usou essa variável já (ver, por exemplo, como zsh
tem problemas com o seu $path
ou $commands
variáveis especiais gama / de hash (a la CSH) que quebrar alguns scripts).
Nota que, além de conchas não suportam essas variáveis, algumas conchas como pdksh / mksh fazer remover -los do ambiente que eles recebem ( bash
remove a um com um nome vazio, ash
, ksh
e bash
remover aquelas cordas de ambiente que não contêm um =
caractere):
$ 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 %%%
%%%
Para resumir, o melhor é ficar com os nomes de variáveis suportados pela maioria das conchas e até mesmo tentar usar letras maiúsculas para variáveis de ambiente (e minúsculas ou maiúsculas e minúsculas para variáveis do shell não-exportados) evitando aqueles que são especiais em conchas (como IFS
, PS1
, BASH_VERSION
...)
Se você precisar definir essa variável em um shell que não as suporte, mas não as descarte, você pode se reexecutar, com algo como:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(obviamente, se você precisar fazer isso no meio do script, isso não ajudará, mas você poderá dar uma olhada nessa abordagem para salvar e restaurar o ambiente de execução do shell em um reexecutor). Ou tente a abordagem do depurador:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(que se parece funcionar com zsh
, yash
, csh
e tcsh
no Linux amd64, mas não com qualquer um dos outros conchas que eu tentei ( mksh
, ksh93
, bash
, dash
)).