Bash, dalla versione 4.3, febbraio 2014 (?), Ha esplicito supporto per variabili di riferimento o riferimenti a nomi (namerefs), oltre "eval", con lo stesso effetto benefico e effetto indiretto, e che può essere più chiaro nei tuoi script e anche più difficile per "dimenticare di 'eval' e correggere questo errore":
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...
e anche:
PARAMETRI
A una variabile può essere assegnato l'attributo nameref usando l'opzione -n ai comandi builtin declare o local (vedere le descrizioni di declare e local di seguito) per creare un nameref o un riferimento a un'altra variabile. Ciò consente di manipolare le variabili indirettamente. Ogni volta che si fa riferimento o si assegna alla variabile nameref, l'operazione viene effettivamente eseguita sulla variabile specificata dal valore della variabile nameref. Un nameref è comunemente usato all'interno delle funzioni della shell per fare riferimento a una variabile il cui nome viene passato come argomento alla funzione. Ad esempio, se un nome di variabile viene passato a una funzione shell come primo argomento, in esecuzione
declare -n ref=$1
all'interno della funzione crea un riferimento alla variabile nameref il cui valore è il nome della variabile passato come primo argomento. I riferimenti e le assegnazioni a ref vengono considerati come riferimenti e assegnazioni alla variabile il cui nome è stato passato come $ 1. Se la variabile di controllo in un ciclo for ha l'attributo nameref, l'elenco delle parole può essere un elenco di variabili shell e un riferimento al nome verrà ⋅ stabilito per ogni parola nell'elenco, a sua volta, quando il ciclo viene eseguito. Non è possibile assegnare l'attributo -n alle variabili di matrice. Tuttavia, le variabili nameref possono fare riferimento a variabili di array e variabili di array sottoscritte. Namerefs può essere set disinserito usando l'opzione -n per l'integrato unset. Altrimenti, se unset viene eseguito con il nome di una variabile nameref come argomento,
Ad esempio ( EDIT 2 : (grazie Ron) ha spaziato (prefissato) il nome della variabile interna alla funzione, per ridurre al minimo gli scontri delle variabili esterne, che dovrebbero finalmente rispondere correttamente, il problema sollevato nei commenti di 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
}
e testando questo esempio:
$ return_a_string result; echo $result
The date is 20160817
Si noti che l'integrato bash "declare", quando usato in una funzione, rende la variabile dichiarata "locale" per impostazione predefinita, e "-n" può anche essere usato con "local".
Preferisco distinguere le variabili "importanti da dichiarare" dalle variabili "noiose locali", quindi usare "dichiarare" e "locale" in questo modo funge da documentazione.
EDIT 1 - (Risposta al commento qui sotto di Karsten) - Non posso più aggiungere commenti qui sotto, ma il commento di Karsten mi ha fatto pensare, quindi ho fatto il seguente test che FUNZIONA FINE, AFAICT - Karsten se leggi questo, ti preghiamo di fornire un set esatto dei passaggi di test dalla riga di comando, mostrando il problema che si presume esiste, poiché questi passaggi seguenti funzionano bene:
$ return_a_string ret; echo $ret
The date is 20170104
(L'ho eseguito proprio ora, dopo aver incollato la funzione sopra in un termine bash - come puoi vedere, il risultato funziona bene.)
function funcName {
è la sintassi pre-POSIX ereditata dai primi ksh (dove aveva differenze semantiche che bash non onora).funcName() {
, con nofunction
, dovrebbe essere usato invece; vedi wiki.bash-hackers.org/scripting/obsolete