如何将值添加到bash中数组名称中包含变量的数组?

如何将值添加到bash中数组名称中包含变量的数组?

我的脚本中有一个数组,其中包含组名列表。此列表没有固定数量的元素。

GROUPS=(group1 group2 group3)

这组 GROUPS 中的每个元素都可以有未知数量的值。我动态创建一组名称中包含变量的数组,其中 VARIABLE 是组名称:

for VARIABLE in "${GROUPS[@]}"
do
  declare -a ARRAY_${VARIABLE}
done

我想迭代一组值,如果满足条件,则将它们作为新元素添加到它们所属的数组中。

for (( VALUES=1; VALUES<=10; VALUES++ ));
do 
  if the VALUE belongs to GROUPx assign it to the array for GROUPx 
    ARRAY_$VARIABLE+=("$VALUES")
  fi
done

这应该以一组数组结束,其中包含属于组的值,即:

ARRAY_group1= 1 2 5 9 10
ARRAY_group2= 3 7 
ARRAY_group3= 4 6 8

但我总是收到 bash: 意外标记“$VALUES”附近的语法错误。如果我只是将它分配给一个名为 ARRAY 的数组,它可以完美工作,但我必须将脚本中的值分配给需要动态创建的未知数量的数组。

我可以将这些值添加到名称包含连接变量的字符串中,然后使用 sed 选择单个值,但我也找不到该表达式的正确语法。

let TEST_$VARIABLE="$TEST_$VARIABLE:$VALUES"
let TEST_$VARIABLE="${TEST_$VARIABLE}:$VALUES"
let TEST_$VARIABLE="$((TEST_$VARIABLE)):$VALUES"
let TEST_$VARIABLE="$((TEST_$VARIABLE))" ":$VALUES"

我尝试了其他一些方法,但它们都遇到了完全相同的问题,bash 确实不喜欢在变量名称中使用变量,但我必须动态创建它们,这意味着我必须在名称中包含变量。

我已经尝试了其他一些方法,但是如果您知道如何在 bash 中可靠地引用名称中包含变量的变量,这样我就可以避免所有语法错误和不良替换错误,我将不胜感激。

Tldr:是否有一些语法可以让 bash 以与 bash 处理 ARRAY[@] 相同的方式处理 ARRAY_$VARIABLE[@]

答案1

名称引用

我认为 nameref 会是你想要的:

name=foo
declare -a array_$name
declare -n target=array_$name
for x in asdf 'white space' ; do target+=("$x"); done 
declare -p array_$name

输出:

declare -a array_foo=([0]="asdf" [1]="white space")

评估、声明、让

另一种更糟糕的方法是使用evaldeclare设置这些值。

eval引用变得很棘手,您不想意外地扩展$值中的任何 s 。

eval "array_$name+=(\"\$x\")"

declare使得实现追加到数组有点困难。如果您知道要分配给的索引,那就相当简单了:

declare "array_$name[$i]=$x"

(获取元素的数量array_$name似乎需要 nameref 或eval再次。)

你提到过let;它有点像declare这里,但适用于算术表达式,因此不太适合一般情况。

name=a; 
let "test_$name=12+34"        # sets test_a to 46
let "test_$name=foo"          # reads the _value_ of variable foo!
let "test_$name=foo bar"      # this is an error.

替代数据结构

或者,如果每个值只能有一个,则反转数据结构,并将每个值的组 id 存储在单个数组中:

for (( val=1; val <= 10; val++ )); do
     groupid=$(find_groupid "$val")
     variables[$val]=$groupid
done

然后遍历整个数组并忽略您不感兴趣的组。

或者,如果您的值不包含任何空格,则只需使用字符串作为内部数组。要循环它们,请执行类似的操作

for group in "${groups[@]}"; do 
    for item in $group; do       # no quotes here, we want wordsplitting
        ...

(或者也使用关联数组来存储组名称。)

相关内容