Bash bietet seit Version 4.3, Februar 2014 (?), Eine explizite Unterstützung für Referenzvariablen oder Namensreferenzen (namerefs), die über "eval" hinausgehen, mit derselben vorteilhaften Leistung und demselben Indirektionseffekt, die in Ihren Skripten möglicherweise klarer und auch schwieriger sind um "zu vergessen, 'auszuwerten' und diesen Fehler zu beheben":
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...
und auch:
PARAMETER
Einer Variablen kann das Attribut nameref mithilfe der Option -n den Deklarations- oder lokal eingebauten Befehlen zugewiesen werden (siehe die Beschreibungen von deklarieren und lokal unten), um ein nameref oder einen Verweis auf eine andere Variable zu erstellen. Dadurch können Variablen indirekt manipuliert werden. Immer wenn auf die nameref-Variable verwiesen oder zugewiesen wird, wird die Operation tatsächlich für die Variable ausgeführt, die durch den Wert der nameref-Variablen angegeben wird. Ein nameref wird üblicherweise in Shell-Funktionen verwendet, um auf eine Variable zu verweisen, deren Name als Argument an die Funktion übergeben wird. Wenn beispielsweise ein Variablenname als erstes Argument an eine Shell-Funktion übergeben wird, wird ausgeführt
declare -n ref=$1
Innerhalb der Funktion wird eine nameref-Variablenreferenz erstellt, deren Wert der Variablenname ist, der als erstes Argument übergeben wird. Referenzen und Zuweisungen an ref werden als Referenzen und Zuweisungen an die Variable behandelt, deren Name als $ 1 übergeben wurde. Wenn die Steuervariable in einer for-Schleife das Attribut nameref hat, kann die Liste der Wörter eine Liste der Shell-Variablen sein, und für jedes Wort in der Liste wird nacheinander eine Namensreferenz erstellt, wenn die Schleife ausgeführt wird. Array-Variablen können nicht das Attribut -n erhalten. Nameref-Variablen können jedoch auf Array-Variablen und tiefgestellte Array-Variablen verweisen. Namerefs können mit der Option -n für das nicht festgelegte integrierte Objekt deaktiviert werden. Andernfalls, wenn unset mit dem Namen einer nameref-Variablen als Argument ausgeführt wird,
Zum Beispiel ( EDIT 2 : (danke Ron) Namespace (vorangestellt) des funktionsinternen Variablennamens, um externe Variablenkonflikte zu minimieren, die das in den Kommentaren von Karsten aufgeworfene Problem endgültig beantworten sollten):
# $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
}
und Testen dieses Beispiels:
$ return_a_string result; echo $result
The date is 20160817
Beachten Sie, dass die eingebaute Bash "deklarieren" bei Verwendung in einer Funktion die deklarierte Variable standardmäßig "lokal" macht und "-n" auch mit "lokal" verwendet werden kann.
Ich bevorzuge es, "wichtige Deklarations" -Variablen von "langweiligen lokalen" Variablen zu unterscheiden, daher dient die Verwendung von "Deklaration" und "lokal" auf diese Weise als Dokumentation.
EDIT 1 - (Antwort auf Kommentar unten von Karsten) - Ich kann unten keine Kommentare mehr hinzufügen, aber Karstens Kommentar hat mich zum Nachdenken gebracht, also habe ich den folgenden Test durchgeführt, der FUNKTIONIERT, AFAICT - Karsten, wenn Sie dies lesen, geben Sie bitte einen genauen Satz an von Testschritten über die Befehlszeile, die das von Ihnen angenommene Problem anzeigen, da diese folgenden Schritte einwandfrei funktionieren:
$ return_a_string ret; echo $ret
The date is 20170104
(Ich habe dies gerade ausgeführt, nachdem ich die obige Funktion in einen Bash-Begriff eingefügt habe - wie Sie sehen können, funktioniert das Ergebnis einwandfrei.)
function funcName {
ist die Legacy-Syntax vor POSIX vom frühen ksh geerbt (wo es semantische Unterschiede gab, die bash nicht berücksichtigt).funcName() {
, mit nofunction
, sollte stattdessen verwendet werden; siehe wiki.bash-hackers.org/scripting/obsolete