Como exportar uma variável que contém um ponto. Recebo 'nome de variável inválido' quando tentei:
export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name
Mesmo escapar do metacaractere ponto (.) também não ajudou
$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
Responder1
Pelo menos para bash
a página de manual define a sintaxe de exportação como:
export [-fn] [name[=word]] ...
Ele também define um "nome" como:
name A word consisting only of alphanumeric characters and under‐
scores, and beginning with an alphabetic character or an under‐
score. Also referred to as an identifier.
Portanto, você realmente não pode definir uma variável como my.home
se ela não fosse um identificador válido.
Tenho certeza de que seu ksh tem uma definição muito semelhante de identificador e, portanto, também não permite esse tipo de variável. (Dê uma olhada em sua página de manual.)
Também tenho certeza de que existe algum tipo de padrão geral (POSIX?) Especificando o que é permitido como identificador (e, portanto, um nome de variável).
Se você realmente precisa desse tipo de variável por algum motivo, você pode usar algo como
env "my.home=/tmp/someDir" bash
para defini-lo de qualquer maneira. Mas, novamente, você não poderá acessá-lo usando a sintaxe normal do shell. Neste caso você provavelmente precisará de outra linguagem como perl:
perl -e 'print $ENV{"my.home"}'
Por exemplo
env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'
deve imprimir seu caminho.
Responder2
Embora as variáveis de ambiente possam ter qualquer nome (incluindo a string 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 das variáveis são limitados a caracteres alfanuméricos ASCII e _
onde o primeiro caractere pode' t seja um dígito (exceto para os parâmetros posicionais e outros especiais como $*
, $-
, $@
,…, (que não são mapeados para as variáveis de ambiente correspondentes)). Observe também que algumas variáveis sãoreservado/especialpor/para o shell.
Exceções a isso:
O
rc
shell e seus derivados gostames
eakanga
suportam qualquer nome, exceto a string vazia, e aqueles que são totalmente numéricos ou contêm=
caracteres (e sempre exportam todas as suas variáveis para o ambiente, e cuidado com variáveis especiais como*
,status
,pid
...):; '%$£"' = test ; echo $'%$£"' test ; '' = x zero-length variable name ;
Porém, utiliza codificação própria para variáveis cujo nome não contém alnums ou para arrays quando passados no ambiente de comandos em execução:
$ 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 e (também
ksh
, mas apenas para caracteres de byte único) suportam alnums no código do idioma atual, não apenas nos ASCII.yash
zsh
bash
$ Stéphane=1 $ echo "$Stéphane" 1
Nesses shells, você poderia alterar o código do idioma para considerar a maioria dos caracteres como alfa, mas isso ainda não funcionaria para caracteres ASCII como
.
. Você pode enganarzsh
ouksh
pensar£
que é uma letra, mas não esse.
ou qualquer outro caractere ASCII (no que diz respeito à permissão de caracteres em nomes de variáveis, não para o[[: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.
objetivo é garantir que não entre em conflito com outras variáveis. Se ele tivesse optado por chamá-lo$sh_version
, então poderia ter scripts potencialmente quebrados que já usavam essa variável (veja, por exemplo, comozsh
há problemas com suas variáveis$path
de$commands
array/hash especiais (a la csh) que quebram alguns scripts).
Observe que, além dos shells não suportarem essas variáveis, alguns shells como pdksh/mksh suportamremoverdo ambiente que recebem ( bash
remove aquele com nome vazio, ash
e ksh
remove bash
as strings 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 %%%
%%%
Resumindo, o melhor é usar nomes de variáveis suportados pela maioria dos shells e até tentar usar letras maiúsculas para variáveis de ambiente (e minúsculas ou maiúsculas e minúsculas para variáveis de shell não exportadas), evitando aquelas que são especiais em shells (como IFS
, PS1
, BASH_VERSION
...).
Se você precisar definir tal variável em um shell que não as suporte, mas não as descarte, você pode reexecutar você mesmo, 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ê pode dar uma olhada emessa abordagempara salvar e restaurar o ambiente de execução do shell durante uma nova execução). Ou tente a abordagem do depurador:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(esse parece funcionar com zsh
, e no Linux amd64, mas não com nenhum dos outros shells yash
que tentei ( , , , )).csh
tcsh
mksh
ksh93
bash
dash
Responder3
Como os outros posts apontam, os shells mais comuns não permitem definir variáveis de ambiente com pontos no nome. No entanto, encontrei situações, principalmente envolvendo Docker e programas invocados, em que o software exigia valores-chave com pontos.
No entanto, em cada uma destas situações, esses pares chave-valor poderiam ser passados para o programa através de outros meios que não apenas variáveis de ambiente. Por exemplo, no Ant, você pode usar o "-propertyfile (nome do arquivo)" para passar uma coleção de valores-chave formatada em arquivo de propriedades. Confd permite "-backend file -file (arquivo yaml)".
Passei as variáveis de ambiente no formato "C__any_value='my.property.key=the value'". Em seguida, mudei a invocação do programa para primeiro gerar o arquivo:
set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt
O set
comando, no Borne Shell, produzirá cada propriedade em uma linha separada no formato
C__any_value='my.property.key=the value'
O awk
comando processará apenas as variáveis de ambiente começando com C__
e, em seguida, extrairá os valores contidos entre aspas simples.
Este método requer que o valor da variável de ambiente seja definido na forma precisa exigida pelo programa de processamento. Além disso, se o valor ou chave da sua propriedade contiver aspas simples, você precisará alterar o caractere separador de campo awk para algo que você sabe que não aparecerá e colocar o valor em volta desse caractere. Por exemplo, para usar %
como separador:
$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value
(a saída precisa dependerá do seu shell.) Você precisará executar etapas extras para decodificar a citação que escapa.
Responder4
A resposta de @michas está correta, mas é possível estendê-la para simular export
funções com nomes de ambiente de ponto.
Para "exportar" tal variável, você pode usar exec
o shell atual com env
o comando. Por exemplo, para exportar test.env=foo
variável, use:
exec env "test.env=foo" $SHELL
Exec substituirá o shell atual por um novo processo, onde o novo processo será uma nova instância do shell atual ( $SHELL
) com variável de ambiente adicional test.env
(adicionada por env "test.env=foo"
). Então após este comando você pode acessá-lo a partir do seu processo, por exemplo:
perl -e 'print $ENV{"test.env"}'