Bash, depuis la version 4.3, février 2014 (?), A un support explicite pour les variables de référence ou les références de nom (namerefs), au-delà de "eval", avec les mêmes performances bénéfiques et effet d'indirection, et qui peuvent être plus clairs dans vos scripts et aussi plus difficiles pour "oublier" eval "et devoir corriger cette erreur":
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...
et aussi:
PARAMÈTRES
Une variable peut être affectée à l'attribut nameref à l'aide de l'option -n aux commandes internes ou locales de déclaration (voir les descriptions de déclarer et local ci-dessous) pour créer un nom de référence ou une référence à une autre variable. Cela permet aux variables d'être manipulées indirectement. Chaque fois que la variable nameref est référencée ou affectée à, l'opération est réellement effectuée sur la variable spécifiée par la valeur de la variable nameref. Un nameref est couramment utilisé dans les fonctions shell pour faire référence à une variable dont le nom est passé en argument à la fonction. Par exemple, si un nom de variable est transmis à une fonction shell comme premier argument, l'exécution
declare -n ref=$1
à l'intérieur de la fonction crée une variable nameref ref dont la valeur est le nom de variable passé comme premier argument. Les références et les affectations à ref sont traitées comme des références et des affectations à la variable dont le nom a été passé à $ 1. Si la variable de contrôle dans une boucle for possède l'attribut nameref, la liste de mots peut être une liste de variables shell, et une référence de nom sera établie pour chaque mot de la liste, à son tour, lorsque la boucle est exécutée. Les variables de tableau ne peuvent pas recevoir l'attribut -n. Cependant, les variables nameref peuvent référencer des variables de tableau et des variables de tableau en indice. Les références de nom peuvent être désactivées à l'aide de l'option -n de la commande intégrée non définie. Sinon, si unset est exécuté avec le nom d'une variable nameref comme argument,
Par exemple ( EDIT 2 : (merci Ron), le nom de variable interne à la fonction (préfixé), pour minimiser les conflits de variables externes, qui devrait enfin répondre correctement, le problème soulevé dans les commentaires de Karsten):
# $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
}
et tester cet exemple:
$ return_a_string result; echo $result
The date is 20160817
Notez que la commande bash "declare", lorsqu'elle est utilisée dans une fonction, rend la variable déclarée "locale" par défaut, et "-n" peut également être utilisée avec "local".
Je préfère distinguer les variables "déclaration importante" des variables "locales ennuyeuses", donc l'utilisation de "déclarer" et "local" de cette manière fait office de documentation.
EDIT 1 - (Réponse au commentaire ci-dessous par Karsten) - Je ne peux plus ajouter de commentaires ci-dessous, mais le commentaire de Karsten m'a fait réfléchir, j'ai donc fait le test suivant qui FONCTIONNE BIEN, AFAICT - Karsten si vous lisez ceci, veuillez fournir un ensemble exact des étapes de test à partir de la ligne de commande, montrant le problème que vous supposez exister, car ces étapes suivantes fonctionnent très bien:
$ return_a_string ret; echo $ret
The date is 20170104
(Je l'ai exécuté tout à l'heure, après avoir collé la fonction ci-dessus dans un terme bash - comme vous pouvez le voir, le résultat fonctionne très bien.)
function funcName {
syntaxe héritée pré-POSIX est héritée du début de ksh (où il y avait des différences sémantiques que bash n'honore pas).funcName() {
, avec nofunction
, doit être utilisé à la place; voir wiki.bash-hackers.org/scripting/obsolete