Как получить значение переменной, если имя переменной хранится в виде строки? - PullRequest
113 голосов
/ 17 декабря 2009

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

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

Контекст:

У меня есть несколько AMI ( Образ машины Amazon ), и я хочу запустить несколько экземпляров каждого AMI. Как только они закончат загрузку, я хочу настроить каждый экземпляр в соответствии с его типом AMI. Я не хочу запекать множество скриптов или секретных ключей внутри любого AMI, поэтому я подготовил обобщенный скрипт запуска и поместил его на S3 с общедоступной ссылкой. В rc.local я поместил небольшой фрагмент кода, который выбирает сценарий запуска и выполняет его. Это все, что у меня есть в AMI. Затем каждый AMI получает доступ к общему сценарию конфигурации, который применим ко всем 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"
...
Когда запускается скрипт запуска, он загружает вышеуказанный файл и source. Затем он проверяет свой тип AMI и выбирает для себя правильный скрипт установки.
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, а экземпляры могут позаботиться о себе.

Ответы [ 5 ]

197 голосов
/ 17 декабря 2009

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

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

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

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

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

24 голосов
/ 17 декабря 2009
X=foo
Y=X
eval "Z=\$$Y"

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

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

Например

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

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

8 голосов
/ 17 декабря 2009

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

eval a=\$$a
Спасибо за ваше время.
4 голосов
/ 16 декабря 2017

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

${(P)a}

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

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

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

Аналогично, если ссылка сама по себе является вложенной, выражение с Флаг обрабатывается так, как если бы он был непосредственно заменен именем параметра. Это ошибка, если эта вложенная подстановка создает массив с более чем одно слово. Например, если ‘name = assoc’, где параметр assoc является ассоциативным массивом, тогда ‘$ {$ {(P) name} [elt]}’ относится к элемент ассоциативной подписи «elt».

0 голосов
/ 17 декабря 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...