【问题标题】:Bash indirect variable assignment inside a functionBash 函数内部的间接变量赋值
【发布时间】:2013-04-14 10:00:20
【问题描述】:

我有一个脚本需要多次评估用户输入,我正在研究的解决方案是将评估位放入一个函数中,每次我需要评估输入时只需调用该函数。 问题是,当我尝试更新$1 变量(引用函数的第一个变量参数)时,我收到错误消息“$VARIABLE command not found”。

代码如下:

function input_handler() {
 if is_integer $1; then
  selid="$1 -1"
  if [[ "$1" -le "0" ]]; then
   echo "Please use a simple positive number!"
  else
   if [[ "$1" -le "${#array[*]}" ]]; then
    eval $1="${array[selid]}"
    echo "Ok, moving on..."
   else
    echo "That number seems too large, try again?"
   fi
  fi
 else
  if [ -e $2/$1 ]; then
   echo "Ok, moving on..."
  else
   echo "That item is not on the list, try again!"
  fi
 fi
}

还有这个命令:

input_handler $doctype $docpath

给出这个输出:

5
./test: line 38: 5=sun: command not found

好的,继续……

现在这几乎是正确的,但我需要的是 doctype=sun,而不是 5=sun,换句话说,我需要的是 $1 变量名而不是它的值。将行 eval $1="${array[selid]}" 更改为 eval doctype="${array[selid]}" 可修复此特定实例。但这并不能解决我的问题,因为我需要在具有不同名称的不同变量上运行此函数。

【问题讨论】:

    标签: bash function variables


    【解决方案1】:

    可能没有完全理解你想要实现的目标,但请查看下一个示例:

    weirdfunc () {
        echo " weirdfunc: variable name is: $1"
        echo " weirdfunc: variable value is: ${!1}"
        eval "$1=$(( ${!1} + 1))" #assign
    }
    
    myvar="5"
    echo "the value of myvar before: $myvar"
    
    weirdfunc myvar #call with the NAME not with the value, so NOT weridfunc $myvar
    
    echo "the value of myvar after: $myvar"
    

    简而言之 - 当你想在被调用函数中对变量 NAME 做任何事情时,你应该传递变量的名称而不是他的值。所以调用函数

    somefunc NAME
    

    而不是

    somefunc $NAME
    

    并使用上述构造获取函数内部的名称和值。

    【讨论】:

    • 也许我应该弄清楚我想做什么。我正在处理的脚本输出文件条目列表并提示用户选择它应该选择的文件,如果一个有效的选择它应该存储在变量 $1 变量中。现在到目前为止一切正常,但这是棘手的部分;为了使脚本更加用户友好,我在每个文件条目前添加了数字。想法是用户可以键入相应的数字而不是完整的文件名。但是为了让它工作,我需要将他的选择“like 5”转换为有效的文件名“like sun”并将其存储在 $1 变量中
    • 如果你想改变一个按名称传递的变量的值,使用上面的结构。如果你想设置 $1 使用@kojiro 的答案,但老实说不明白为什么要这样做,当你可以使用任何辅助变量时......你能做的最好 - 显示一个非常短的例子 - 没有任何不相关的“如果"s 和主要部分 - 不仅仅是功能......
    • 你完全正确!我通过添加一个辅助变量 helper="${array[selid]}" 而不是 eval $1="${array[selid]}" 解决了这个问题,并且在函数之外调用它: input_handler $doctype $docpath<br>doctype=$helper 抱歉,如果不清楚,我对 stackoverflow 和 Bash 脚本一般来说是新手。感谢您的所有帮助!
    • @Dan-SimonMyrland:在 cmets 中的代码周围使用反引号 like `this` please
    • @Dan-SimonMyrland 如果您需要在函数之外修改变量,答案会告诉您如何正确操作。
    【解决方案2】:

    您无法使用传统赋值更新$1 的值,但您可以使用内置set 更新位置参数。

    $ f() { echo "$@"; set -- a b c; echo "$@"; echo $2; }
    $ f 1 2 3
    1 2 3
    a b c
    b
    

    请记住,这将清除您每次未重新设置的所有位置参数,因此如果您想保留它,则需要设置$2

    您最好的选择可能是将位置参数中的值分配给名称,然后只使用名称。

    【讨论】:

      【解决方案3】:

      如果您保护变量名,Bash 将评估并分配给 $1,而不是尝试执行 $1=value。

      eval "$1"=${array[selid]}
      

      【讨论】:

        【解决方案4】:

        位置参数是只读的。所以你想做的事情是不可能的。你应该做类似的事情

        foo=$1
        

        然后使用$foo 而不是$1

        【讨论】:

        • 好的,但我仍然需要 $1 的名称而不是值,这可能吗?
        • 位置参数不是只读的。您可以使用set 更改它们。
        猜你喜欢
        • 2012-04-13
        • 2018-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多