Bash从4.3版(2014年2月)开始,对引用变量或名称引用(namerefs)提供了明确的支持,除了“ eval”之外,还具有相同的性能和间接效果,并且在脚本中可能更清晰,也更难要“忘记'评估',并且必须解决此错误”:
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...
并且:
参数
可以使用-n选项为声明或本地内置命令(请参见下面的声明和本地说明)为变量分配nameref属性,以创建nameref或对另一个变量的引用。这允许变量被间接操纵。每当引用或分配nameref变量时,实际上都会对nameref变量的值指定的变量执行操作。在外壳函数中,通常使用nameref来引用变量,该变量的名称作为该函数的参数传递。例如,如果将变量名作为第一个参数传递给shell函数,则运行
declare -n ref=$1
函数内部将创建一个nameref变量ref,其值是作为第一个参数传递的变量名称。对ref的引用和赋值被视为对名称作为$ 1传递的变量的引用和赋值。如果for循环中的控制变量具有nameref属性,则单词列表可以是shell变量列表,并且在执行循环时,将依次为列表中的每个单词建立名称引用。数组变量不能赋予-n属性。但是,nameref变量可以引用数组变量和下标数组变量。可以使用-n选项对未设置的内置变量名进行设置。否则,如果使用nameref变量的名称作为参数执行unset,
例如(EDIT 2:(感谢Ron)对函数内部变量名称进行命名(前缀),以最大程度地减少外部变量冲突,该冲突最终应能正确地解决,由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
}
并测试此示例:
$ return_a_string result; echo $result
The date is 20160817
请注意,内置的bash“ declare”在函数中使用时,默认情况下使声明的变量为“ local”,“-n”也可以与“ local”一起使用。
我更喜欢将“重要的声明”变量与“无聊的本地”变量区分开,因此以这种方式使用“声明”和“本地”充当文档。
编辑1-(在下面由Karsten回复评论)-我无法再在下面添加评论,但是Karsten的评论让我开始思考,所以我进行了以下测试,即:FINES FINE,AFAICT-Karsten,如果您阅读此书,请提供准确的设置命令行中的测试步骤,显示您认为存在的问题,因为以下步骤可以正常工作:
$ return_a_string ret; echo $ret
The date is 20170104
(在将上述函数粘贴到bash术语中后,我才运行此代码-如您所见,结果运行良好。)
function funcName {
POSIX之前的旧语法是从早期的ksh继承的(bash在语义上有区别,bash无法兑现)。funcName() {
,如果没有function
,则应改用;参见wiki.bash-hackers.org/scripting/obsolete