Exportando uma variável com ponto (.)

39

Como exportar uma variável que possui 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 o ponto de escape do metacaractere também não ajudou

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
user1587504
fonte
11
infelizmente, não está listado quando eu digitei / procurei uma pergunta semelhante. Desculpe. ..
user1587504 04/10

Respostas:

50

Pelo menos para basha 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.homeela não é um identificador válido.

Tenho certeza de que seu ksh tem uma definição muito semelhante de um identificador e, portanto, não permite esse tipo de variável também. (Dê uma olhada na sua página de manual.)

Também tenho certeza de que há algum tipo de padrão geral (POSIX?) Especificando o que é permitido como identificador (e, portanto, um nome de variável).


Se você realmente precisar desse tipo de variável, por algum motivo, poderá 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. Nesse caso, você provavelmente precisará de outro idioma 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.

michas
fonte
É por causa da integração da formiga. E infelizmente não permite configurar / exportar variáveis ​​do unix. Aceitando sua resposta. ..
user1587504 04/10
11
O ant é geralmente configurado por uma única variável de ambiente chamada ANT_OPTSou por ~ / .antrc. Não há necessidade de nomes de variáveis ​​de ambiente estranhos para a própria formiga.
Michas
8

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 rcshell e seus derivados, como ese akangaapoiar 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, yashe zsh(também bashmas 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 zshou kshpensar 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).

  • ksh93possui 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 zshtem problemas com o seu $pathou $commandsvariá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 ( bashremove a um com um nome vazio, ash, kshe bashremover 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, cshe tcshno Linux amd64, mas não com qualquer um dos outros conchas que eu tentei ( mksh, ksh93, bash, dash)).

Stéphane Chazelas
fonte
11
mksh(e pdksh) de fato constroem os processos do ambiente que geram, completamente do zero, usando apenas os parâmetros exportados no atual ambiente de execução do shell, portanto, não há como passar essas variáveis ​​por esses shells. (Observe que as variáveis ​​que são passadas estão sujeitas a alterações; por exemplo, estou planejando oferecer suporte a exportações de array por mkshum dia.)
mirabilos
0

Como as outras postagens apontam, os shells mais comuns não permitem definir variáveis ​​de ambiente com pontos no nome. No entanto, encontrei situações, particularmente envolvendo o Docker e programas invocados, em que o software exigia valores-chave com períodos.

No entanto, em cada uma dessas situações, esses pares de valores-chave podem ser passados ​​para o programa por outros meios além das variáveis ​​de ambiente. Por exemplo, no Ant, você pode usar o "-propertyfile (filename)" para transmitir uma coleção de valores-chave formatada em um arquivo de propriedades. Confd permite "arquivo de back-end - arquivo (arquivo yaml)".

Passei as variáveis ​​de ambiente no formato "C__any_value = 'my.property.key = the value'". Troquei a chamada do programa para primeiro gerar o arquivo:

set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt

O setcomando, no Borne Shell, produzirá cada propriedade em uma linha separada no formulário

C__any_value='my.property.key=the value'

O awkcomando processará apenas as variáveis ​​de ambiente iniciadas por C__e depois extrairá os valores contidos nas aspas simples.

Este método requer que o valor da variável de ambiente seja definido na forma precisa que o programa de processamento exige. Além disso, se o valor ou a chave da sua propriedade contiver aspas simples, será necessário alterar o caractere separador de campo awk para algo que você sabe que não aparecerá e cercar o valor com esse 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 está escapando.

Groboclown
fonte