Bash: определение локальной локальной переменной, невидимой для поиска script
Скажем, у меня есть файл bash script config.sh
. Это означало, что source'd использует другие сценарии, а определенные переменные используются как настройка сценариев верхнего уровня.
Проблема заключается в том, что если config.sh
имеет временную переменную и ее имя конфликтует с переменной верхнего уровня скрипта, она разбивает верхний уровень.
config.sh:
TMP1=abc
CONFIG_INPUT_DIR="$TMP1"/in
CONFIG_OUTPUT_DIR="$TMP1"/out
верхний уровень script:
TMP1=def
source config.sh
echo $TMP1
Последний echo
печатает abc
, а не def
.
Решение 1
Мое текущее решение состоит в том, чтобы добавить случайную строку к временному имени переменной, чтобы сделать почти невозможным конфликт. например:
TMP1_vFc9Uiew=abc
CONFIG_INPUT_DIR="$TMP1_vFc9Uiew"/in
CONFIG_OUTPUT_DIR="$TMP1_vFc9Uiew"/out
unset TMP1_vFc9Uiew
что является болезненным и делает код трудным для чтения, кроме того, он не идеален.
Решение 2 с использованием ключевого слова local
После некоторого поиска я познакомился с ключевым словом local
.
Но когда я просто объявляю TMP1
как local
, bash жалуется, что config.sh: line 1: local: can only be used in a function
.
Итак, мое другое решение состоит в том, чтобы вставить всю конфигурацию script в качестве функции:
function config_func_rZ0Yqkpm() {
local TMP1=abc
CONFIG_INPUT_DIR="$TMP1"/in
CONFIG_OUTPUT_DIR="$TMP1"/out
}
config_func_rZ0Yqkpm
unset config_func_rZ0Yqkpm
который лучше предыдущего решения в ремонтопригодности и удобочитаемости, но есть некоторая возможность конфликта, а также решение 1.
Вопрос
Я хочу знать более надежное и умное решение без каких-либо конфликтов.
Спасибо.
Ответы
Ответ 1
Трюк, который я узнал из утилиты keychain
, использует одну программу для сборки файла source
-able, содержащего только переменные которые вы хотите экспортировать из своей программы. Вы можете изменить свои script на echo
переменные, которые вы хотите установить, а затем вывести результаты из своей программы:
$ echo $FOO
$ source <(echo FOO=bar)
$ echo $FOO
bar
$
Я использовал echo FOO=bar
для моделирования более крупного script; ваша программа, вероятно, более активна. Важная часть состоит в том, что вы должны изменить свою программу, чтобы вывести переменные и значения, которые вы хотите установить, а не просто устанавливать их. Это позволяет вам определять, какие переменные выставлять и какие из них удерживать приватно за счет другого процесса оболочки.
Ответ 2
Вы можете избежать переменных и использовать функции в config.sh для хранения ваших значений:
get_dirname() { echo "abc"; }
CONFIG_INPUT_DIR="$(get_dirname)/in"
CONFIG_OUTPUT_DIR="$(get_dirname)/out"
unset -f get_dirname
Если вы все еще обеспокоены конфликтом имен для функций, это не поможет вам.
Ответ 3
Метод "ssh-agent":
config.sh
#!/bin/bash
TMP=abc
printf "CONFIG_INPUT_DIR=%s/in" "$TMP"
printf "CONFIG_OUTPUT_DIR=%s/out" "$TMP"
Основная программа:
TMP1=def
eval $(config.sh)
echo $TMP1
Ответ 4
Два обычных метода создания уникального имени файла - использовать функцию mktemp, которая гарантирует создание уникального имени файла или встраивание PID в имя файла. PID будет находиться в переменной "$$".