Exportando uma variável com ponto (.) nela

Exportando uma variável com ponto (.) nela

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 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.homese 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 rcshell e seus derivados gostam ese akangasuportam 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.yashzshbash

    $ 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 enganar zshou kshpensar £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).

  • 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 .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, como zshhá problemas com suas variáveis $path​​​​de $commandsarray/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 ( bashremove aquele com nome vazio, ashe kshremove bashas 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 yashque tentei ( , , , )).cshtcshmkshksh93bashdash

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 setcomando, no Borne Shell, produzirá cada propriedade em uma linha separada no formato

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

O awkcomando 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 exportfunções com nomes de ambiente de ponto.

Para "exportar" tal variável, você pode usar execo shell atual com envo comando. Por exemplo, para exportar test.env=foovariá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"}'

informação relacionada