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

357
35

Как получить значение переменной 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, и экземпляры могут позаботиться о себе.

спросил(а) 2021-01-19T14:26:47+03:00 9 месяцев, 1 неделя назад
1
Решение
504

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


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

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

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


ответил(а) 2021-01-19T14:26:47+03:00 9 месяцев, 1 неделя назад
192

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

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


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

Например


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

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

ответил(а) 2021-01-19T14:26:47+03:00 9 месяцев, 1 неделя назад
137

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

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

ответил(а) 2021-01-19T14:26:47+03:00 9 месяцев, 1 неделя назад
65

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


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

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

ответил(а) 2021-01-19T14:26:47+03:00 9 месяцев, 1 неделя назад
47

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


${(P)a}


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


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

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

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


ответил(а) 2021-01-19T14:26:47+03:00 9 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема