#bash
#bash
Вопрос:
Почему это не дает никаких выходных данных (кроме новой строки) вместо «foo»? В коде используется ссылка на имя, которая была введена в bash 4.3 и является «ссылкой на другую переменную», которая «позволяет манипулировать переменными косвенно».
И что следует сделать, чтобы защититься от этого, при написании кода для библиотеки?
#!/usr/bin/bash
setret() {
local -n ret_ref=$1
local ret="foo"
ret_ref=$ret
}
setret ret
echo $ret
Прогоняя его bash -x
, у меня закружилась голова, потому что, похоже, он должен выводить то, foo
что я ожидал:
setret ret
local -n ret_ref=ret
local ret=foo
ret_ref=foo
echo
Интересно, что это выводит bar
, а не foo
.
#!/usr/bin/bash
setret() {
local -n ret_ref=$1
ret_ref="bar"
local ret="foo"
ret_ref=$ret
}
setret ret
echo $ret
С таким же запутанным bash -x
выводом:
setret ret
local -n ret_ref=ret
ret_ref=bar
local ret=foo
ret_ref=foo
echo bar
bar
Ответ №1:
Я надеюсь, что это ценно для других, потому что запрос ожидаемого результата в #bash
IRC-канале получил ответ от одного из его постоянных пользователей foo
, чего я и ожидал.
Затем они меня просветили. ссылки на имена просто работают не так, как я думал. local -n
не настроен ret_ref
для ссылки на $1
. Скорее, он в основном хранит строку ret
в ret_ref
, помеченную для использования в качестве ссылки при ее использовании.
Итак, хотя мне показалось, что это ret_ref
будет ссылаться на ret
переменную вызывающего объекта, это происходит только до тех пор, пока функция не определит свою собственную локальную ret
переменную, тогда вместо этого она будет ссылаться на эту.
Единственный гарантированный способ защититься от этого при написании кода для библиотеки — в любой функции, которая использует namerefs, добавлять ко всем переменным, не являющимся nameref, префикс имени функции в следующих строках:
#!/usr/bin/bash
setret() {
local -n ___setret_ret_ref=$1
local ___setret_ret="foo"
___setret_ret_ref=$___setret_ret
}
setret ret
echo $ret
Очень некрасиво, но необходимо, чтобы избежать столкновений. (Конечно, есть менее уродливые способы сделать это, которые, вероятно, сработают, но не так наверняка.)