首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过引用传递参数

通过引用传递参数
EN

Stack Overflow用户
提问于 2009-02-12 14:45:31
回答 8查看 47.5K关注 0票数 52

我想问一下,是否可以通过引用将参数传递给脚本函数:

例如,在C++中执行如下所示的操作:

代码语言:javascript
复制
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中,我想做一些类似这样的事情:

代码语言:javascript
复制
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

任何想法都将不胜感激。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2018-05-11 05:21:27

现在是2018年,这个问题应该更新一下。至少在Bash中,从Bash 4.3-alpha开始,您可以使用nameref通过引用传递函数参数:

代码语言:javascript
复制
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.

  • Inside

  • ,使用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,它的安全陷阱很多,而且有很好的文档记录。

票数 42
EN

Stack Overflow用户

发布于 2010-05-18 04:19:37

使用辅助函数upvar

代码语言:javascript
复制
# 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()中像这样使用它

代码语言:javascript
复制
local "$1" && upvar $1 new

要返回多个变量,请使用另一个辅助函数upvars。这允许在一个调用中传递多个变量,从而避免在一个upvar调用更改了另一个后续upvar调用中使用的变量时可能发生的冲突。

有关帮助函数upvars的详细信息,请参阅:http://www.fvue.nl/wiki/Bash:_Passing_variables_by_reference

问题在于:

代码语言:javascript
复制
eval $1=new

如果$1恰好包含一个命令,那么它是不安全的:

代码语言:javascript
复制
set -- 'ls /;true'
eval $1=new  # Oops

最好使用printf -v

代码语言:javascript
复制
printf -v "$1" %s new

但是printf -v不能赋值数组。

此外,如果变量恰好声明为local,则evalprintf都不起作用

代码语言:javascript
复制
g() { local b; eval $1=bar; }  # WRONG
g b                            # Conflicts with `local b'
echo $b                        # b is empty unexpected

即使local bunset,冲突也会一直存在

代码语言:javascript
复制
g() { local b; unset b; eval $1=bar; }  # WRONG
g b                                     # Still conflicts with `local b'
echo $b                                 # b is empty unexpected
票数 17
EN

Stack Overflow用户

发布于 2009-02-12 07:24:30

我已经找到了一种方法来做到这一点,但我不确定这是否正确:

代码语言:javascript
复制
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 ...

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/540298

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档