Importando variáveis ​​em um script de shell de outro sem executar o script de shell referido

Importando variáveis ​​em um script de shell de outro sem executar o script de shell referido

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.

informação relacionada