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...
, а также:
PARAMETERS
Переменная может бытьназначил атрибут nameref с помощью опции -n встроенным командам объявлений или локальных команд (см. описание объявлений и локальных файлов ниже), чтобы создать именованную ссылку или ссылку на другую переменную.Это позволяет косвенно манипулировать переменными.Всякий раз, когда на переменную nameref ссылаются или назначают, операция фактически выполняется над переменной, указанной в значении переменной nameref.Nameref обычно используется в функциях оболочки для ссылки на переменную, имя которой передается в качестве аргумента функции.Например, если имя переменной передается в функцию оболочки в качестве первого аргумента, выполнение
declare -n ref=$1
внутри функции создает переменную nameref ref, значением которой является имя переменной, переданное в качестве первого аргумента.Ссылки и присваивания ref обрабатываются как ссылки и присваивания переменной, имя которой было передано как $ 1.Если управляющая переменная в цикле for имеет атрибут nameref, список слов может быть списком переменных оболочки, и ссылка на имя будет установлена для каждого слова в списке, в свою очередь, при выполнении цикла.Переменным массива не может быть присвоен атрибут -n.Тем не менее, переменные nameref могут ссылаться на переменные массива и подписанные переменные массива.Namerefs можно отключить с помощью опции -n встроенной функции unset.В противном случае, если unset выполняется с именем переменной nameref в качестве аргумента, переменная, на которую ссылается переменная nameref, будет не установлена.
Например ( EDIT 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 - как видите, результат работает просто отлично.)