Подтвердить что ты не робот

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.

Вопрос

Я хочу знать более надежное и умное решение без каких-либо конфликтов.

Спасибо.

4b9b3361

Ответ 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 будет находиться в переменной "$$".