我想问一下,是否可以通过引用将参数传递给脚本函数:
例如,在C++中执行如下所示的操作:
void boo(int &myint) { myint = 5; }
int main() {
int t = 4;
printf("%d\n", t); // t->4
boo(t);
printf("%d\n", t); // t->5
}因此,在BASH中,我想做一些类似这样的事情:
function boo ()
{
var1=$1 # now var1 is global to the script but using it outside
# this function makes me lose encapsulation
local var2=$1 # so i should use a local variable ... but how to pass it back?
var2='new' # only changes the local copy
#$1='new' this is wrong of course ...
# ${!1}='new' # can i somehow use indirect reference?
}
# call boo
SOME_VAR='old'
echo $SOME_VAR # -> old
boo "$SOME_VAR"
echo $SOME_VAR # -> new任何想法都将不胜感激。
发布于 2018-05-11 05:21:27
现在是2018年,这个问题应该更新一下。至少在Bash中,从Bash 4.3-alpha开始,您可以使用nameref通过引用传递函数参数:
function boo()
{
local -n ref=$1
ref='new'
}
SOME_VAR='old'
echo $SOME_VAR # -> old
boo SOME_VAR
echo $SOME_VAR # -> new这里的关键部分是:
将变量的名称传递给boo,而不是它的值:boo SOME_VAR,not boo $SOME_VAR.
local -n ref=$1为$1命名的变量声明一个nameref,这意味着它不是对$1本身的引用,而是对一个名称为$1的变量的引用,即本例中的SOME_VAR。右边的值应该只是一个命名现有变量的字符串:获取该字符串的方式并不重要,因此像local -n ref="my_var"或local -n ref=$(get_var_name)这样的东西也可以使用。在允许/需要这样做的上下文中,declare也可以取代local。有关更多information.信息,请参阅chapter on Shell Parameters in Bash Reference Manual
这种方法的优点是(可以说)更好的可读性,最重要的是,避免了eval,它的安全陷阱很多,而且有很好的文档记录。
发布于 2010-05-18 04:19:37
使用辅助函数upvar
# Assign variable one scope above the caller.
# Usage: local "$1" && upvar $1 value [value ...]
# Param: $1 Variable name to assign value to
# Param: $* Value(s) to assign. If multiple values, an array is
# assigned, otherwise a single value is assigned.
# NOTE: For assigning multiple variables, use 'upvars'. Do NOT
# use multiple 'upvar' calls, since one 'upvar' call might
# reassign a variable to be used by another 'upvar' call.
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
upvar() {
if unset -v "$1"; then # Unset & validate varname
if (( $# == 2 )); then
eval $1=\"\$2\" # Return single value
else
eval $1=\(\"\${@:2}\"\) # Return array
fi
fi
}并在Newfun()中像这样使用它
local "$1" && upvar $1 new要返回多个变量,请使用另一个辅助函数upvars。这允许在一个调用中传递多个变量,从而避免在一个upvar调用更改了另一个后续upvar调用中使用的变量时可能发生的冲突。
有关帮助函数upvars的详细信息,请参阅:http://www.fvue.nl/wiki/Bash:_Passing_variables_by_reference。
问题在于:
eval $1=new如果$1恰好包含一个命令,那么它是不安全的:
set -- 'ls /;true'
eval $1=new # Oops最好使用printf -v
printf -v "$1" %s new但是printf -v不能赋值数组。
此外,如果变量恰好声明为local,则eval和printf都不起作用
g() { local b; eval $1=bar; } # WRONG
g b # Conflicts with `local b'
echo $b # b is empty unexpected即使local b为unset,冲突也会一直存在
g() { local b; unset b; eval $1=bar; } # WRONG
g b # Still conflicts with `local b'
echo $b # b is empty unexpected发布于 2009-02-12 07:24:30
我已经找到了一种方法来做到这一点,但我不确定这是否正确:
Newfun()
{
local var1="$1"
eval $var1=2
# or can do eval $1=2 if no local var
}
var=1
echo var is $var # $var = 1
newfun 'var' # pass the name of the variable…
echo now var is $var # $var = 2所以我们传递变量名,而不是值,然后使用eval ...
https://stackoverflow.com/questions/540298
复制相似问题