Bash, od wersji 4.3, lutego 2014 (?), Ma wyraźne wsparcie dla zmiennych referencyjnych lub referencji nazw (namerefs), wykraczających poza „eval”, z tą samą korzystną wydajnością i efektem pośrednim, i które mogą być wyraźniejsze w twoich skryptach, a także trudniejsze aby „zapomnieć o„ ewaluacji ”i naprawić ten błąd”:
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...
i również:
PARAMETRY
Zmiennej można przypisać atrybut nameref za pomocą opcji -n do wbudowanych poleceń deklaracji lub lokalnych poleceń (patrz opisy deklaracji i lokalnych poniżej), aby utworzyć nazwę lub odwołanie do innej zmiennej. Pozwala to na manipulowanie zmiennymi pośrednio. Ilekroć zmienna nameref jest przywoływana lub przypisywana, operacja jest faktycznie wykonywana na zmiennej określonej przez wartość zmiennej nameref. Nazeref jest często używany w funkcjach powłoki w celu odniesienia do zmiennej, której nazwa jest przekazywana jako argument do funkcji. Na przykład, jeśli nazwa zmiennej zostanie przekazana do funkcji powłoki jako pierwszy argument, uruchomiona
declare -n ref=$1
wewnątrz funkcji tworzy zmienną nameref ref, której wartością jest nazwa zmiennej przekazywana jako pierwszy argument. Referencje i przypisania do referencji są traktowane jak referencje i przypisania do zmiennej, której nazwa została przekazana jako $ 1. Jeśli zmienna kontrolna w pętli for ma atrybut nameref, lista słów może być listą zmiennych powłoki, a odniesienie nazwy zostanie utworzone dla każdego słowa na liście, po kolei, gdy pętla zostanie wykonana. Zmienne tablicowe nie mogą mieć atrybutu -n. Jednak zmienne nameref mogą odwoływać się do zmiennych tablicowych i zmiennych tablic dolnych. Nazwy można ⋅ rozbroić za pomocą opcji -n wbudowanego rozbrojenia. W przeciwnym razie, jeśli polecenie unset zostanie wykonane z nazwą zmiennej nameref jako argumentem,
Na przykład ( EDYCJA 2 : (dziękuję Ron) wstawił (przedrostek) nazwę zmiennej wewnętrznej funkcji, aby zminimalizować kolizje zmiennych zewnętrznych, które ostatecznie powinny poprawnie odpowiedzieć, problem podniesiony w komentarzach Karstena):
# $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
}
i testowanie tego przykładu:
$ return_a_string result; echo $result
The date is 20160817
Zauważ, że wbudowana bash „deklaruj”, gdy jest używana w funkcji, domyślnie powoduje, że zadeklarowana zmienna jest „lokalna”, a „-n” może być również używane z „lokalną”.
Wolę odróżniać zmienne „ważne deklarować” od „nudnych zmiennych lokalnych”, więc użycie „deklarowania” i „lokalnego” w ten sposób działa jako dokumentacja.
EDYCJA 1 - (Odpowiedź na komentarz poniżej przez Karstena) - Nie mogę już dodawać komentarzy poniżej, ale komentarz Karstena zmusił mnie do myślenia, więc zrobiłem następujący test, który DZIAŁA WYGODNIE, AFAICT - Karsten, jeśli to czytasz, proszę podać dokładny zestaw kroków testowych z wiersza poleceń, pokazując, że istnieje problem, który, jak zakładasz, działa dobrze:
$ return_a_string ret; echo $ret
The date is 20170104
(Uruchomiłem to właśnie teraz, po wklejeniu powyższej funkcji do terminu bash - jak widać, wynik działa dobrze).
function funcName {
Nawiasem mówiąc , jest to starsza składnia sprzed POSIX odziedziczona po wczesnym ksh (gdzie miała różnice semantyczne, których bash nie honoruje).funcName() {
,function
zamiast, należy użyć zamiast; patrz wiki.bash-hackers.org/scripting/obsolete