arrays - Bash 数组名称选择

标签 arrays bash dynamic

有没有办法动态访问数组名称?

以下循环有效:

#!/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/

相关文章:

javascript - 在 Javascript 中获取查询字符串数组值

机器编程时无法将 double 转换为 double *(高斯消除)项目

c - 需要帮助改进一个小型 C 程序

Ajax 网站中的 Javascript 插件

dynamic - 后记缩放

c++ - 这个 "size of array"模板函数是如何工作的?

ruby-on-rails - 查询数组内部值的事件记录

bash - 期望脚本模拟SNMP

bash - 使用远程数据制作 Cobra 标志 bash 完成

c - 如何在具有动态字符串的函数中使用 malloc 并且不在末尾添加符号