有没有办法动态访问数组名称?
以下循环有效:
#!/bin/bash
for i in 1 2 3 4 5; do
for j in 1 2 3 4 5; do
state="i=$i, j=$j"
case "$i" in
1) p_1+=("$state");;
2) p_2+=("$state");;
3) p_3+=("$state");;
4) p_4+=("$state");;
5) p_5+=("$state");;
*) break;;
esac
done
done
for i in {0..5}; do echo "${p_1[$i]}"; done
for i in {0..5}; do echo "${p_2[$i]}"; done
for i in {0..5}; do echo "${p_3[$i]}"; done
for i in {0..5}; do echo "${p_4[$i]}"; done
for i in {0..5}; do echo "${p_5[$i]}"; done
输出如下:
i=1, j=1
i=1, j=2
i=1, j=3
i=1, j=4
i=1, j=5
i=2, j=1
i=2, j=2
i=2, j=3
i=2, j=4
i=2, j=5
i=3, j=1
i=3, j=2
i=3, j=3
i=3, j=4
i=3, j=5
i=4, j=1
i=4, j=2
i=4, j=3
i=4, j=4
i=4, j=5
i=5, j=1
i=5, j=2
i=5, j=3
i=5, j=4
i=5, j=5
但是它中间有那个丑陋的 case 语句,而且不够灵活。我希望能够扩展它而不必扩展 case 语句。
我尝试过这个:
for i in 1 2 3 4 5; do
for j in 1 2 3 4 5; do
$(p_${i})+=("$i, j=$j") # Does not work
${p_$i}+=("$i, j=$j") # neither does this
done
done
是否有一些语法魔法可以让我动态定义和访问数组名称?非常感谢任何帮助。
我尝试了“michas”解决方案,如下所示:
#!/bin/bash
for i in 1 2 3 4 5; do
for j in 1 2 3 4 5; do
state=("i=$i, j=$j")
eval "p_$i+=($state)"
#also tried
# IFS="_" state=("i=$i,j=$j") #failed to show j=
# IFS="_" eval "p_$i=($state)" # failed to show j=
done
done
for i in {0..5}; do
for j in {0..5}; do
res=p_$i
eval "echo \$p_$i cooked: ${!res}"
#IFS="_" eval "echo \$p_$i cooked: ${!res}" #failed to show j=
done
done
但即使有注释掉的区域,所有区域都返回以下(删节的)输出:
i=1, cooked: i=1,
:
i=1, cooked: i=1,
i=1, cooked: i=1,
:
i=3, cooked: i=3,
i=3, cooked: i=3,
:
i=4, cooked: i=4,
i=4, cooked: i=4,
:
i=5, cooked: i=5,
i=5, cooked: i=5,
好的,解决了我的问题。这个循环作为第一个循环工作(仍然受到限制,但现在仅限于没有“+”的字符串),但我可以喜欢它。
#!/bin/bash
for i in 1 2 3 4 5; do
for j in 1 2 3 4 5; do
state=$(echo "i=$i, j=$j" | tr " " "+")
eval "p_$i+=($state)"
done
done
for i in {0..5}; do
for j in {0..5}; do
res=p_$i[$j]
eval "echo ${!res}"| tr '+' ' '
done
done
谢谢!
最佳答案
p_5=foo
i=5
v=p_$i
echo ${!v}
# => foo
让我们引用 bash 手册页:
${parameter}
The value of parameter is substituted. The braces are required
when parameter is a positional parameter with more than one
digit, or when parameter is followed by a character which is not
to be interpreted as part of its name.
If the first character of parameter is an exclamation point (!), a
level of variable indirection is introduced. Bash uses the value of
the variable formed from the rest of parameter as the name of the vari‐
able; this variable is then expanded and that value is used in the rest
of the substitution, rather than the value of parameter itself. This
is known as indirect expansion. The exceptions to this are the expan‐
sions of ${!prefix*} and ${!name[@]} described below. The exclamation
point must immediately follow the left brace in order to introduce
indirection.
但这仅适用于访问值,对于其他 shell 来说是不可移植的。
作为替代方案,您始终可以使用eval
:
p_5=foo
i=5
eval "echo \$p_$i" # => foo
eval "p_$i=bar"
echo $p_5 # => bar
手册页显示:
eval [arg ...]
The args are read and concatenated together into a single com‐
mand. This command is then read and executed by the shell, and
its exit status is returned as the value of eval. If there are
no args, or only null arguments, eval returns 0.
关于arrays - Bash 数组名称选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19623861/