将位置参数分配给一行中的多个变量

时间:2016-12-26 19:35:30

标签: bash function parameter-passing

我想知道是否可以将bash函数中的位置参数分配给一行中的多个变量。

以下工作但需要多个分配行:

foo () {
   var1=${1}
   var2=${2}
   var3=${3}
   echo "var1=$var1   var2=$var2   var3=$var3"
}

foo 11 "22 22" 33 # Correct result: var1=11   var2=22 22   var3=33

以下内容将输入参数分配到一行,但它没有正确处理第二个参数:

bar () {
    read var1 var2 var3 <<<"$@"
    echo "var1=$var1   var2=$var2   var3=$var3"
}

bar 11 "22 22" 33 # Incorrect result: var1=11   var2=22   var3=22 33

4 个答案:

答案 0 :(得分:1)

g() {
  for k in m p q
  do
    local "$k"="$1"
    shift
  done
  echo m="$m" p="$p" q="$q"
}
g 11 '22 22' 33

请注意POSIX的local is not specified,但确实如此 specified by Bash and Dash

答案 1 :(得分:0)

您需要转义空格字符:

bar 11 "22\ 22" 33

给出:

var1=11   var2=22 22   var3=33

答案 2 :(得分:-2)

尝试反序列化$@的方法已被破坏。如果你想要健壮的代码,请不要使用它们。

只需使用循环:

for v in var1 var2 var3; do
    eval $v='$1'
    shift
done

请注意,由于单引号,eval的使用是100%安全的。要在函数中使用,在Bash中,您可以改为使用localdeclare -g

foo() {
    local v
    for v in var1 var2 var3; do
        local "$v=$1"
        shift
    done
    printf '%s\n' "var1=$var1" "var2=$var2" "var3=$var3"
}

请注意,如果您没有提供足够的参数,shift可能会抱怨。

此主题还有许多其他可能的变化,以适应您的需求。

这远远优于其他一些答案:

  • 对嵌入的换行符,反斜杠,有趣的字符等没有任何问题。
  • 没有子shell,临时文件等

最后注意事项:如果您因为我建议eval而感到有人想要进行投票,请确保比我更了解 eval做什么,以及为什么危险;确保你明白为什么在这种情况下它是100%安全的;最后,留下评论来解释为什么你比我更清楚为什么这是错误的。

答案 3 :(得分:-2)

对于名为k q w(POSIX友好)的变量

bar1(){ j=0; for i in k q w; do eval $i=\$$((j+=1)); done;
    echo "k=$k   q=$q   w=$w"
  }
echo "bar1"
bar1 11 "22 22" 33 # Correct result: k=11   q=22 22   w=33

如果变量的名称可能会有所改变;使用数组(避免使用eval):

bar2 (){ var=("" "$@")     # To make var[0]="" 
         for i in {1..3}; do printf '%-12s' "var$i=${var[i]} "; done; echo
       }
echo "bar2"
bar2 11 "22 22" 33 # Correct result: var1=11   var2=22 22   var3=33

一些较长的解决方案:

您可以使用以下内容:

bar3() {
         i=1
         for var; do declare var$((i++))="$var"; done
         echo "var1=$var1   var2=$var2   var3=$var3"
}
echo "bar3"
bar3 11 "22 22" 33

declare执行与eval类似的工作,但更安全。

但实际上,你应该考虑的是使用数组变量:
""是为var[0]分配一个空值。

bar4(){  var=("" "$@")
         echo "var1=${var[1]} var2=${var[2]}" "var3=${var[3]}"
      }
echo "bar4"
bar4 11 "22 22" 33

当然,如果你必须有不同名称的变量,你可以从上面构建一个eval:

bar5(){
         var=("" "$@")
         eval "var1=\${var[1]} var2=\${var[2]} var3=\${var[3]}"
         echo "var1=$var1      var2=$var2      var3=$var3"
      }
echo "bar5"
bar5 11 "22 22" 33

在这种情况下,eval非常安全。