Поиск переменных оболочки по имени, косвенно
Скажем, у меня есть имя переменной, хранящееся в другой переменной:
myvar=123
varname=myvar
теперь, я хотел бы получить 123, просто используя переменную $varname.
Есть ли прямой путь для этого? Я не нашел такого встроенного bash для поиска по имени, поэтому придумал следующее:
function var { v="\$$1"; eval "echo "$v; }
так
var $varname # gives 123
В конце концов это выглядит не так уж плохо, но мне интересно, пропустил ли я что-то более очевидное. Спасибо заранее!
Ответы
Ответ 1
На странице справочной страницы bash:
${!varname}
Если первый символ параметра является восклицательным знаком, уровень вводится переменная косвенность. Bash использует значение переменной, сформированной из остальной части параметра, как имя переменной; эта переменная затем расширяется и это значение используется в остальной части подстановка, а не значение самого параметра. Это известный как косвенное расширение.
Ответ 2
Существует не прямой синтаксис Posix, соответствующий только bash
ism. Обычно я это делаю:
eval t="\$$varname"
Это будет работать с любой оболочкой Posix, включая те системы, где bash
- это оболочка входа, а /bin/sh
- это что-то меньшее и быстрое, например ash
. Мне нравится bash и использовать его для моей оболочки входа, но я избегаю бахизмов в командных файлах.
Примечание. Одна из проблем с написанием сценариев bash - это то, что даже если вы можете рассчитывать на установку bash, это может быть где угодно на пути. В этом случае неплохо было бы использовать полностью общий стиль /usr/bin/env
shebang, но обратите внимание, что это все еще не на 100% переносимо и имеет проблемы с безопасностью.
Ответ 3
${!varname}
должен сделать трюк
$ var="content"
$ myvar=var
$ echo ${!myvar}
content
Ответ 4
Я обычно смотрю Advance Bash -Scripting Guide, когда мне нужно освежить свои навыки Bash.
Относительно вашего вопроса посмотрите Непрямые ссылки
Обозначение:
Version < 2
\$$var
Version >= 2
${!varname}
Ответ 5
# bmuSetIndirectVar()
# TO DOUBLE CHECK THIS COMMENT AND DEMO
# This function is an helper to read indirect variables.
# i.e. get the content of a variable whose name is saved
# within an other variable. Like:
# MYDIR="/tmp"
# WHICHDIR="MYDIR"
# bmuSetIndirectVar "WHICHDIR" "$MYDIR"
#
bmuSetIndirectVar(){
tmpVarName=$1
locVarName=$1
extVarName=$2
#echo "debug Ind Input >$1< >$2<"
eval tmpVarName=\$$extVarName
#echo "debug Ind Output >$tmpVarName< >$extVarName<"
export $locVarName="${tmpVarName}"
}
В настоящее время я использую эту небольшую функцию. Я не совсем этому доволен, и я видел различные решения в Интернете (если бы мог вспомнить, что я напишу их здесь), но, похоже, это сработает. Внутри этих нескольких строк уже есть избыточность и дополнительные данные, но это было полезно для отладки.
Если вы хотите увидеть его на месте, то есть где я его использую, проверьте:
https://github.com/mariotti/bmu/blob/master/bin/backmeup.shellfunctions.sh
Конечно, это не лучшее решение, но заставило меня продолжать работу, в
надеюсь, что я смогу заменить его чем-то чуть более общим в ближайшее время.