Bash, оскільки версія 4.3, feb 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 для оголошень або локальних вбудованих команд (див. Описи оголошень та місцевих нижче) для створення імені refre або посилання на іншу змінну. Це дозволяє непрямим чином маніпулювати змінними. Щоразу, коли на змінну nameref посилається ⋅ або присвоюється їй, операція фактично виконується на змінній, визначеній значенням змінної nameref. Іменний реф зазвичай використовується у функціях оболонки для позначення змінної, ім'я якої передається як аргумент для функції. Наприклад, якщо ім'я змінної передається функції оболонки як її перший аргумент, запущений
declare -n ref=$1
всередині функції створюється переменная nameref ref, значенням якої є назва змінної, передана як перший аргумент. Посилання та завдання для перегляду трактуються як посилання та присвоєння змінній, ім'я якої було передано як $ 1. Якщо контрольна змінна в циклі for for має атрибут nameref, у списку слів може бути список змінних оболонок, а посилання на ім’я буде встановлено⋅ для кожного слова у списку, у свою чергу, коли цикл виконується. Змінній масиву не можна надати атрибут -n. Однак змінні nameref можуть посилатись на змінні масиву та на підписані масиви змінних. Namerefs можна відмінити, використовуючи опцію -n для скидання вбудованого. В іншому випадку, якщо unset виконується з ім'ям змінної 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 "оголосити", коли використовується у функції, за замовчуванням робить задекларовану змінну "локальною", а "-n" також можна використовувати з "local".
Я вважаю за краще відрізняти змінні "важливого оголошення" від "нудних локальних" змінних, тому використання "заявити" та "локальне" таким чином діє як документація.
EDIT 1 - (Відповідь на коментар нижче від Karsten) - Я більше не можу додавати коментарі нижче, але коментар 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