Поиск переменных оболочки по имени, косвенно

Скажем, у меня есть имя переменной, хранящееся в другой переменной:

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

Конечно, это не лучшее решение, но заставило меня продолжать работу, в надеюсь, что я смогу заменить его чем-то чуть более общим в ближайшее время.