Bash, начиная с версии 4.3, февраль 2014 (?), Имеет явную поддержку ссылочных переменных или ссылок на имена (namerefs), помимо «eval», с той же выгодной эффективностью и эффектом косвенности, которые могут быть более понятными в ваших сценариях, а также сложнее «забыть« eval »и исправить эту ошибку»:
declare [-aAfFgilnrtux] [-p] [name[=value] ...]
typeset [-aAfFgilnrtux] [-p] [name[=value] ...]
Declare variables and/or give them attributes
...
-n Give each name the nameref attribute, making it a name reference
to another variable. That other variable is defined by the value
of name. All references and assignments to name, except for⋅
changing the -n attribute itself, are performed on the variable
referenced by name's value. The -n attribute cannot be applied to
array variables.
...
When used in a function, declare and typeset make each name local,
as with the local command, unless the -g option is supplied...
а также:
ПАРАМЕТРЫ
Переменной можно присвоить атрибут nameref, используя опцию -n для встроенных команд объявлений или локальных команд (см. Описания объявлений и локальных ресурсов ниже), чтобы создать именованную ссылку или ссылку на другую переменную. Это позволяет косвенно манипулировать переменными. Всякий раз, когда на переменную nameref ссылаются или назначают, операция фактически выполняется над переменной, указанной значением переменной nameref. Nameref обычно используется в функциях оболочки для ссылки на переменную, имя которой передается в качестве аргумента функции. Например, если имя переменной передается функции оболочки в качестве первого аргумента, выполняется
declare -n ref=$1
внутри функции создается переменная nameref ref, значением которой является имя переменной, переданное в качестве первого аргумента. Ссылки и присваивания ref обрабатываются как ссылки и присваивания переменной, имя которой было передано как $ 1. Если управляющая переменная в цикле for имеет атрибут nameref, список слов может быть списком переменных оболочки, и ссылка на имя будет установлена для каждого слова в списке, в свою очередь, при выполнении цикла. Переменным массива не может быть присвоен атрибут -n. Тем не менее, переменные nameref могут ссылаться на переменные массива и подписанные переменные массива. Namerefs можно отключить, используя опцию -n встроенной функции unset. В противном случае, если unset выполняется с именем переменной nameref в качестве аргумента,
Например ( РЕДАКТИРОВАТЬ 2 : (спасибо, Рон), пространство имен (с префиксом) имени внутренней переменной функции, чтобы минимизировать конфликты внешних переменных, которые должны окончательно ответить правильно, проблема, поднятая в комментариях Карстена):
# $1 : string; your variable to contain the return value
function return_a_string () {
declare -n ret=$1
local MYLIB_return_a_string_message="The date is "
MYLIB_return_a_string_message+=$(date)
ret=$MYLIB_return_a_string_message
}
и тестирование этого примера:
$ return_a_string result; echo $result
The date is 20160817
Обратите внимание, что встроенная команда bash «Declare», когда используется в функции, делает объявленную переменную «локальной» по умолчанию, и «-n» также может использоваться с «локальной».
Я предпочитаю отличать переменные «важное объявление» от «скучных локальных» переменных, поэтому использование «объявления» и «локального» таким образом действует как документация.
РЕДАКТИРОВАТЬ 1 - (Ответ на комментарий ниже от Karsten) - я не могу больше добавлять комментарии ниже, но комментарий Karsten заставил меня задуматься, поэтому я сделал следующий тест, который РАБОТАЕТ КАЧЕСТВЕННО, AFAICT - Karsten, если вы читаете это, пожалуйста, предоставьте точный набор шагов теста из командной строки, показывающих, что проблема, по вашему мнению, существует, потому что эти следующие шаги работают просто отлично:
$ return_a_string ret; echo $ret
The date is 20170104
(Я запустил это только сейчас, после вставки вышеупомянутой функции в термин bash - как видите, результат работает просто отлично.)
function funcName {
унаследованный до POSIX синтаксис унаследован от раннего ksh (где у него были семантические различия, которые bash не соблюдает).funcName() {
, с нетfunction
, следует использовать вместо; см. wiki.bash-hackers.org/scripting/obsolete