我想知道是否可以将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
答案 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中,您可以改为使用local
或declare -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
可能会抱怨。
此主题还有许多其他可能的变化,以适应您的需求。
这远远优于其他一些答案:
最后注意事项:如果您因为我建议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非常安全。