Exportando uma variável com ponto (.) nela

33

Como exportar uma variável que tenha um ponto nela. Eu recebo "nome de variável inválido" quando tentei:

 export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name

Mesmo escapando de metacaracteres ponto (.) din't ajudou

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
    
por user1587504 04.10.2013 / 09:05

3 respostas

41

Pelo menos para bash , a página man define a sintaxe de exportação como:

export [-fn] [name[=word]] ...

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 , pois não é um identificador válido.

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

Também estou muito certo de que há algum tipo de padrão geral (POSIX?) especificando o que é permitido como um 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 assim mesmo. Mas, novamente, você não poderá acessá-lo usando a sintaxe normal do shell. Nesse 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.

    
por 04.10.2013 / 09:15
6

Enquanto variáveis de ambiente podem ter qualquer nome (incluindo a string vazia) não contendo um sinal de igual ou um byte nulo, shells mapeiam variáveis de ambiente para variáveis shell e na maioria das shells, nomes de variáveis são limitados a caracteres alfanuméricos ASCII e _ onde o primeiro caractere não pode ser um dígito (exceto 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ão reserved / special por / para o shell.

Exceções a isso:

  • O shell rc e seus derivados, como es e akanga , suportam qualquer nome, exceto a sequência vazia, e aqueles que são todos numéricos ou contêm = caracteres (e sempre exportam todas as variáveis para o ambiente e tenha 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 arrays quando passado no ambiente dos comandos que estão sendo executados:

    $ rc -c '+ = zzz; __ = zzz; a = (zzz xxx); env' | sed -n /zzz/l
    __2b=zzz$
    __5f_=zzz$
    a=zzz
    $ Stéphane=1
    $ echo "$Stéphane"
    1
    
    1xxx$ $ 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) suportam alnums na localidade atual, não apenas na ASCII.

    $ 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 %%%
    %%%
    

    Nesses shells, você pode alterar o local para considerar a maioria dos caracteres como alfa, mas ainda assim isso não funcionaria para caracteres ASCII como . . Você pode enganar zsh ou ksh pensando que £ é uma letra, mas não que . ou qualquer outro caractere ASCII (onde é permitido caracteres em nomes de variáveis, não para [[:alpha:]] glob, por exemplo) .

  • ksh93 tem variáveis especiais cujo nome contém um ponto como ${.sh.version} , mas elas não são mapeadas para variáveis de ambiente e são especiais. O . é para garantir que não conflite com outras variáveis. Se ele tivesse escolhido chamá-lo de $sh_version , ele poderia ter scripts potencialmente quebrados que já usavam essa variável (veja, por exemplo, como zsh tem problemas com suas variáveis de matriz / hash especiais $path ou $commands csh) que quebra alguns scripts.

Note que, além dos shells que não suportam essas variáveis, alguns shells como pdksh / mksh fazem removê-los do ambiente que recebem ( bash remove aquele com um nome vazio, ash , ksh e bash remove as cadeias de ambiente que não contêm um caractere = ):

#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
Para resumir, o melhor é ficar com 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 uma variável como essa em um shell que não a suporte, mas não a descartará, poderá recorrer novamente, com algo como:

gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"

(obviamente, se você precisar fazer isso no meio do script, isso não vai ajudar, mas você pode dar uma olhada em essa abordagem para salvar e restaurar o ambiente de execução do shell em uma nova execução). Ou tente a abordagem do depurador:

; '%$£"' = test
; echo $'%$£"'
test
; '' = x
zero-length variable name
;

(esse parece funcionar com zsh , yash , csh e tcsh no Linux amd64, mas não com nenhum dos outros shells que eu tentei ( mksh , ksh93 , bash , dash )).

    
por 04.10.2013 / 14:08
0

Como as outras postagens apontam, os shells mais comuns não permitem a configuração de variáveis de ambiente com pontos no nome. No entanto, encontrei situações, particularmente envolvendo o Docker e programas chamados, em que o software exigia valores de 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 que não apenas variáveis de ambiente. Por exemplo, em Ant, você pode usar o "-propertyfile (filename)" para passar uma coleção formatada de valores-chave em um arquivo de propriedades. Confd permite "arquivo de arquivo -backend (arquivo yaml)".

Eu passei as variáveis de ambiente no formulário "C__any_value = 'my.property.key = the value'". Então eu mudei a invocação do programa para primeiro gerar o arquivo:

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

O comando set , em Borne Shell, produzirá cada propriedade em uma linha separada na forma

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

O comando awk processará apenas as variáveis de ambiente iniciando com C__ e, em seguida, extrairá os valores contidos nas aspas simples.

Esse 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 da propriedade ou a chave contiverem aspas simples, você precisará alterar o caractere de separador de campo awk para algo que você sabe que não aparecerá e colocar o valor com esse caractere. Por exemplo, para usar % como o 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 adicionais para decodificar o escape da cotação.

    
por 27.03.2019 / 17:55