Импорт переменных в один скрипт оболочки из другого без выполнения указанного скрипта оболочки

Импорт переменных в один скрипт оболочки из другого без выполнения указанного скрипта оболочки

У меня есть 2 скрипта оболочки, file1.sh и file2.sh

файл1.sh

#!/usr/bin/env bash 
export var1="/data/share"
export var2='password'
echo "Hello"

файл2.sh

#!/usr/bin/env bash 
source file1.sh
echo $var1
echo $var2

Когда я запускаю file2.sh, я получаю следующий вывод

Hello
/data/share
password

Но мой ожидаемый результат:

/data/share
password

file1.sh выполняется при ссылке в file2.sh. Как импортировать только переменные в file2.sh без выполнения file1.sh?

решение1

Есть три варианта, которые я использую, когда у меня есть скрипт bash, который я хочу вести себя по-разному при его вызове и при его выполнении (или, другими словами, иметь элементы данных в скрипте, к которым я хочу получить доступ без выполнения какого-либо кода в это время). Комментарии в некоторой степени затронули их.

Вариант первый

Определите, когда осуществляется закупка, и завершите «закупку» в подходящее время

Разделите скрипт на две части, выйдите из скрипта, если он получен, прежде чем перейти к нижней второй части

Создайте верхнюю часть скрипта с определениями (функции/назначения переменных и т. д.), но без прямого выполнения кода.

Перед началом раздела исполняемого кода поместите логику, которая завершит выполнение скрипта, если он обнаружит, что он находится в режиме source. Следующий сегмент кода сделает это:


файл1.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 


файл2.sh

#!/usr/bin/env bash 
source file1.sh
echo "$var1"
echo "$var2"


Вывод запуска ./file2.sh

$ ./file2.sh 
/data/share
password

Вариант два

Этот режим обычно используется только в сложных ситуациях, и для этого конкретного примера он излишен. Я создаю функцию в файле, который хочу использовать в качестве источника, и в этой функции определяю, что должно быть доступно вызывающему. В данном случае это две экспортированные переменные. Обычно я использую этот режим, когда у меня есть ассоциативные массивы, которые в противном случае практически невозможно обработать. Кроме того, файл tmp должен быть удален вызывающим; но в этом случае я этого не сделал:


файл1.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


файл2.sh

#!/usr/bin/env bash 
source $(./file1.sh export)


echo "$var1"
echo "$var2"

Вывод от выполнения file2.sh такой же, как и выше.

Вариант 3

Последний распространенный способ, которым я справляюсь с этим, — это просто файл библиотеки, который содержит только определения и не имеет кода, который будет выполняться при получении или прямом запуске. Это просто вопрос разделения вашего кода. У меня есть группа bash 'libs', которые содержат часто используемые функции, и на основе каждого проекта я обычно настраиваю небольшую библиотеку с исходным кодом для хранения данных конфигурации (констант). Если эти данные включают заполненные массивы, то я также буду использовать версию Варианта 2.

решение2

Если все ваши переменные экспортируются одинаково (экспортировать foo=bar), то вы можете легко получить их все, используяБашФункция замены процесса:

source <(grep '^export .*=' file1.sh)

Выдержка из страницы руководства:

Подстановка процессов Подстановка процессов поддерживается в системах, которые поддерживают именованные каналы (FIFO) или метод именования открытых файлов /dev/fd. Он принимает форму <(list) или >(list). Список процессов запускается с его входом или выходом, подключенным к FIFO или некоторому файлу в /dev/fd. Имя этого файла передается в качестве аргумента текущей команде в результате расширения. Если используется форма >(list), запись в файл предоставит входные данные для списка. Если используется форма <(list), файл, переданный в качестве аргумента, должен быть прочитан для получения вывода списка.

Связанный контент