Quero que meu script leia um arquivo contendo pares de chave / valor de variáveis de ambiente para definir e depois defini-los.
Até agora, eu tenho o seguinte:
#!/bin/bash
cat $1 | while read kv
do
key=${kv%=*}
val=`echo ${kv#*=} | sed 's/^"\|"$//g'`
export $key="$val"
done
E eu quero ler um arquivo como este:
XAUTHLOCALHOSTNAME="localhost"
DISPLAY=":0"
XAUTHORITY="/tmp/some-XAuthority"
Eu só preciso dessas variáveis no escopo durante a duração do script, portanto não preciso resolver o problema de definir uma variável no script para o escopo pai .
Nos meus testes, acho que meu problema está export $key="$val"
, então acho que só preciso de um substituto para essa linha.
bash
shell-script
environment-variables
palswim
fonte
fonte
key=${kv%%=*}
é melhor do quekey=${kv%=*}
porque %% e ## diferem de% e # para saber se a parte removida é a parte mais curta ou mais longa removívelRespostas:
export $key=$val
deve funcionar muito bembash
. Suspeito que seu problema seja o pipe (|
). Todos os comandos em um pipeline são executados em um subshell. No seu exemplo, a instânciabash
que está executando o seu script dividirá 2 subshells: um paracat $1
e outro para owhile read ...
. As variáveis são atribuídas e exportadas no subshell executando o loop while e, em seguida, todas elas são lançadas imediatamente quando o subshell sai. Uma maneira de corrigir isso é não gerar sub-conchas. Em vez de um uso inútil de gato , tente o redirecionamento:O BashFAQ 24 explica isso com muito mais detalhes.
Uma abordagem alternativa é apenas originar o arquivo, com as exportações lançadas em:
A
<( )
é substituição processo.Como uma nota adicional de cautela, como você está lendo variáveis de ambiente de um argumento, certifique-se de que o arquivo de argumento
$1
seja uma fonte confiável, para que não possa fazer coisas ruins ao seu script.fonte
cat
. Mas, o script com redirecionamento funciona agora, obrigado!( jw013 já deu uma resposta correta , mas quero apontar mais alguns problemas.)
O lado direito de um pipeline é executado em seu próprio subshell no bash (assim como na maioria dos outros shells, as exceções são ATT ksh e zsh). Então, você está definindo as variáveis de ambiente no subshell que executa o loop, mas não no processo principal do shell.
Aqui há uma solução fácil, que é substituir o uso inútil de
cat
um redirecionamento:Em geral, se você precisar pré-processar a entrada, coloque o loop e o restante do script (pelo menos a parte que precisa das variáveis alteradas) dentro de um bloco.
Observe que, em geral,
while read line; do …
não itera completamente sobre as linhas de entrada. Consulte Por que éwhile IFS= read
usado com tanta frequência, em vez deIFS=; while read..
? para uma explicação. O idioma correto para iterar nas linhas de entrada éAqui, a remoção do espaço em branco à esquerda e à direita não importa, pois não deve haver nenhuma entrada de amostra, mas você pode precisar
-r
evitar a expansão da barra invertida. É possível quewhile read line
seja de fato uma maneira correta de ler sua entrada (mas suspeito apenas se os valores das variáveis não contiverem novas linhas). Também é possível que seu formato de entrada seja ambíguo ou mais complexo para analisar. Verifique o que acontece se um dos valores das variáveis contiver um caractere de nova linha, aspas duplas ou barra invertida.Um ponto em que você definitivamente está manipulando a entrada é quando extrai o valor:
Primeiro, você precisa de usar as aspas em torno da substituição de variáveis:
echo "${kv#*=}"
; caso contrário, o shell executa a divisão de palavras e a geração de nome de arquivo (ou seja, globbing) nele. Segundo,echo
não é uma maneira confiável de imprimir uma string, porque algumas strings que começam com a-
são tratadas como opções e algumas shells executam expansão de barra invertida no argumento. Uma maneira confiável e portátil de imprimir uma string éprintf %s "${kv#*=}"
. Além disso, se o valor abranger várias linhas, o programa sed atuará em cada um separadamente, o que está errado. Esta é corrigível, mas não há um método mais fácil, que é a utilização de instalações de manipulação de strings do shell:val=${kv#*=}; val=${val#\"}; val=${val%\"}
.Supondo que sua entrada seja analisada corretamente com uma planície
read
, aqui está uma maneira mais simples de analisá-la, aproveitando aIFS
configuração para dividir cada linha:fonte
Outra boa opção pode ser colocar
export
o arquivo no arquivo e fornecê-lo:e depois:
fonte
/ env
roteiro
fonte