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

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?

Mathew
источник
1
Вы не можете сделать это. source значит выполнить. Наиболее очевидное решение - поместить определения переменных в файл конфигурации и использовать их в обоих сценариях.
Michael Vehrs
Может повторить линию с этим [[ $1 == "SourceIt" ]] & echo "Hello" после этого вы можете получить var из скрипта. Используйте это как это /path/of/file.sh SourceIt
makgun
1
7 вопросов и 0 Принимает , Пожалуйста, посмотрите на: Что мне делать, когда кто-то отвечает на мой вопрос?
Cyrus

Ответы:

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.

Argonauts
источник
2

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

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

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

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

A. Loiseau
источник