3

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

file1.sh

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

file2.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?

2 ответа2

3

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

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

Определить, когда получен источник, и завершить «поиск» в соответствующее время.

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

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

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


file1.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 


file2.sh

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


Выход работает ./file2.sh

$ ./file2.sh 
/data/share
password

Вариант второй

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


file1.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


file2.sh

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


echo "$var1"
echo "$var2"

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

Вариант 3

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

2

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

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

Извлечение справочной страницы:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .