Bash, since version 4.3, feb 2014(?), has explicit support for reference variables or name references (namerefs), beyond "eval", with the same beneficial performance and indirection effect, and which may be clearer in your scripts and also harder to "forget to 'eval' and have to fix this error":
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...
and also:
PARAMETERS
A variable can be assigned the nameref attribute using the -n option to the
declare or local builtin commands (see the descriptions of declare and local
below) to create a nameref, or a reference to another variable. This allows
variables to be manipulated indirectly. Whenever the nameref variable is⋅
referenced or assigned to, the operation is actually performed on the variable
specified by the nameref variable's value. A nameref is commonly used within
shell functions to refer to a variable whose name is passed as an argument to⋅
the function. For instance, if a variable name is passed to a shell function
as its first argument, running
declare -n ref=$1
inside the function creates a nameref variable ref whose value is the variable
name passed as the first argument. References and assignments to ref are
treated as references and assignments to the variable whose name was passed as⋅
$1. If the control variable in a for loop has the nameref attribute, the list
of words can be a list of shell variables, and a name reference will be⋅
established for each word in the list, in turn, when the loop is executed.
Array variables cannot be given the -n attribute. However, nameref variables
can reference array variables and subscripted array variables. Namerefs can be⋅
unset using the -n option to the unset builtin. Otherwise, if unset is executed
with the name of a nameref variable as an argument, the variable referenced by⋅
the nameref variable will be unset.
For example (EDIT 2: (thank you Ron) namespaced (prefixed) the function-internal variable name, to minimize external variable clashes, which should finally answer properly, the issue raised in the comments by 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
}
and testing this example:
$ return_a_string result; echo $result
The date is 20160817
Note that the bash "declare" builtin, when used in a function, makes the declared variable "local" by default, and "-n" can also be used with "local".
I prefer to distinguish "important declare" variables from "boring local" variables, so using "declare" and "local" in this way acts as documentation.
EDIT 1 - (Response to comment below by Karsten) - I cannot add comments below any more, but Karsten's comment got me thinking, so I did the following test which WORKS FINE, AFAICT - Karsten if you read this, please provide an exact set of test steps from the command line, showing the problem you assume exists, because these following steps work just fine:
$ return_a_string ret; echo $ret
The date is 20170104
(I ran this just now, after pasting the above function into a bash term - as you can see, the result works just fine.)
function funcName {
is pre-POSIX legacy syntax inherited from early ksh (where it had semantic differences that bash doesn't honor).funcName() {
, with nofunction
, should be used instead; see wiki.bash-hackers.org/scripting/obsolete – Charles Duffyfunction myFunction { blah; }
is fine; it'sfunction myFunction() { blah }
that is not fine, i.e the use of parenthesis with the keyword function. – Will