
Eu tenho 2 scripts de shell, file1.sh e file2.sh
arquivo1.sh
#!/usr/bin/env bash
export var1="/data/share"
export var2='password'
echo "Hello"
arquivo2.sh
#!/usr/bin/env bash
source file1.sh
echo $var1
echo $var2
Quando executo file2.sh, recebo a seguinte saída
Hello
/data/share
password
Mas minha saída esperada é
/data/share
password
file1.sh está sendo executado quando referido em file2.sh. Como importo as variáveis somente no arquivo2.sh sem executar o arquivo1.sh?
Responder1
Existem três opções que uso quando tenho um script bash que desejo que se comporte de maneira diferente quando for originado e quando for executado (ou em outras palavras, tenho itens de dados em um script ao qual desejo acessar sem executar nenhum código naquele tempo). Os comentários tocaram neles até certo ponto.
opção um
Determinar quando será adquirido e encerrar o 'sourcing' no momento apropriado
Separe o script em duas seções, saia do script quando originado antes de chegar à segunda seção inferior
Crie uma seção superior do script com definições (funções/atribuições de variáveis/etc), mas sem execução direta de código.
Pouco antes de a seção de código executável começar, coloque a lógica que sairá do script se detectar que ele está sendo originado. O seguinte segmento de código fará isso:
arquivo1.sh
#!/usr/bin/env bash
export var1="/data/share"
export var2='password'
# --- End Definitions Section ---
# check if we are being sourced by another script or shell
[[ "${#BASH_SOURCE[@]}" -gt "1" ]] && { return 0; }
# --- Begin Code Execution Section ---
echo "Hello"
echo $var1
echo $var2
arquivo2.sh
#!/usr/bin/env bash
source file1.sh
echo "$var1"
echo "$var2"
Saída da execução de ./file2.sh
$ ./file2.sh
/data/share
password
Opção dois
Este geralmente é usado apenas em situações complexas e, neste exemplo específico, é um exagero. Eu crio uma função no arquivo que desejo originar e nessa função determino o que deve estar disponível para o chamador. Neste caso são as duas variáveis exportadas. Normalmente eu uso esse modo quando tenho matrizes associativas, que de outra forma são quase impossíveis de distribuir. Além disso, o arquivo tmp deve ser excluído pelo chamador; mas não fiz neste caso:
arquivo1.sh
#!/usr/bin/env bash
export var1="/data/share"
export var2='password'
exportCfg() {
tmpF=$(mktemp)
declare -p var1 var2 > "$tmpF"
echo "$tmpF"
}
if [ "$1" == "export" ]; then
exportCfg;
exit 0;
fi
echo "Hello"
echo $var1
echo $var2
arquivo2.sh
#!/usr/bin/env bash
source $(./file1.sh export)
echo "$var1"
echo "$var2"
A saída da execução de file2.sh é a mesma acima
Opção 3
A última maneira comum de lidar com isso é simplesmente com um arquivo de biblioteca que contém apenas definições e não possui código que será executado quando originado ou executado diretamente. Isso é simplesmente uma questão de dividir seu código. Eu tenho um grupo de 'libs' do bash que contém funções usadas com frequência e, por projeto, geralmente configura uma pequena biblioteca de origem para armazenar dados de configuração (constantes). Se esses dados incluírem matrizes preenchidas, também usarei uma versão da Opção 2.
Responder2
Se todas as suas variáveis forem exportadas da mesma maneira (exportar foo = barra), então você pode obter todos eles facilmente usandofestarecurso de substituição de processo:
source <(grep '^export .*=' file1.sh)
Extrato da página de manual:
Substituição de Processo A substituição de processo é suportada em sistemas que suportam pipes nomeados (FIFOs) ou o método /dev/fd para nomear arquivos abertos. Assume a forma de <(lista) ou >(lista). A lista de processos é executada com sua entrada ou saída conectada a um FIFO ou algum arquivo em /dev/fd. O nome deste arquivo é passado como argumento para o comando atual como resultado da expansão. Se o formulário >(list) for usado, escrever no arquivo fornecerá entrada para a lista. Se a forma <(list) for usada, o arquivo passado como argumento deverá ser lido para obter a saída da lista.