Как получить значение переменной, если имя переменной хранится как строка?

Как получить значение переменной bash, если у меня есть имя переменной как строка?

var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.

Контекст:

У меня есть AMI (Amazon Machine Image), и я хочу запустить несколько экземпляров каждого AMI. Как только они закончат загрузку, я хочу настроить каждый экземпляр в соответствии со своим типом AMI. Я не хочу выпекать много скриптов или секретных ключей внутри AMI, поэтому я подготовил обобщенный запуск script, и я положил его на S3 с общедоступной ссылкой. В rc.local я помещаю небольшой фрагмент кода, который извлекает запуск script и выполняет его. Это все, что у меня есть в ОИМ. Затем каждый AMI обращается к общей конфигурации script, которая применима ко всем AMI и специальным сценариям установки для каждого. Эти сценарии являются закрытыми и для доступа к ним требуется подписанный URL.

Итак, теперь, когда я запускаю экземпляр AMI (my_private_ami_1), я передаю подписанный URL для еще одного файла, представленного на S3, который содержит подписанный URL для всех частных скриптов в терминах пары ключ/значение.

config_url="http://s3.amazo.../config?signature"
my_private_ami_1="http://s3.amazo.../ami_1?signature"
...
Когда запускается запуск script, он загружает указанный выше файл и source его. Затем он проверяет свой тип AMI и выбирает правильную настройку script для себя.
ami\_type=GET AMI TYPE #ex: sets ami\_type to my\_private\_ami\_1
setup\_url=GET THE SETUP FILE URL BASED ON AMI\_TYPE # this is where this problem arises

Итак, теперь у меня может быть общий код, который может запускать экземпляры, независимо от их типов AMI, и экземпляры могут позаботиться о себе.

Ответ 1

Вы можете использовать ${!a}:

var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'

Это пример косвенного расширения параметров:

Базовая форма расширения параметров - это ${parameter}. Значение parameter подставляется.

Если первый символ parameter является восклицательным знаком (!), Он вводит уровень косвенной косвенности. Bash использует значение переменной, сформированной из остальной части parameter в качестве имени переменной; эта переменная затем раскрывается, и это значение используется в остальной части замещения, а не в значении самого parameter.

Ответ 2

X=foo
Y=X
eval "Z=\$$Y"

устанавливает Z в "foo"

Соблюдайте осторожность eval, так как это может привести к отказу кода через значения в ${Y}. Это может вызвать вред при введении кода.

Например

Y="\`touch /tmp/eval-is-evil\`"

создаст /tmp/eval-is-evil. Это также может быть несколько rm -rf /, конечно.

Ответ 3

Модифицированные ключевые слова для поиска и Got:).

eval a=\$$a
Спасибо за ваше время.

Ответ 4

Для моих знакомых пользователей zsh способ выполнить то же самое, что и принятый ответ:

${(P)a}

Он называется Замена имени параметра

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

Если используется с вложенным параметром или подстановкой команды, результат который будет использоваться как имя параметра таким же образом. Например, если у вас есть "foo = bar" и "bar = baz", строки ${(P) foo}, ${(P) ${foo}}, а ${(P) $(эхо-бар)} будет расширен до 'baz.

Аналогично, если ссылка сама вложена, выражение с флаг обрабатывается так, как если бы он был напрямую заменен именем параметра. Это ошибка, если эта вложенная подстановка создает массив с большим количеством чем одно слово. Например, если 'name = assoc, где параметр является ассоциативным массивом, то "$ {$ {(P) name} [elt]} относится к элемент ассоциативного индексированного" elt.

Ответ 5

современные оболочки уже поддерживают массивы (и даже ассоциативные массивы). Поэтому, пожалуйста, используйте их и используйте меньше eval.

var1="this is the real value"
array=("$var1")
# or array[0]="$var1"

тогда, когда вы хотите вызвать его, echo ${array [0]}

Ответ 6

На основании ответа: https://unix.stackexchange.com/a/111627

###############################################################################
# Summary: Returns the value of a variable given it name as a string.
# Required Positional Argument: 
#   variable_name - The name of the variable to return the value of
# Returns: The value if variable exists; otherwise, empty string ("").
###############################################################################
function get_value_of()
{
    local variable_name=$1
    local variable_value=""
    if [ -n "$(set | grep "^$variable_name=")" ]; then
        eval variable_value="\$$variable_name"
    fi
    echo "$variable_value"
}

test=123
get_value_of test
# 123
test="\$(echo \"something nasty\")"
get_value_of test
# $(echo "something nasty")