我的脚本中有一个数组,其中包含组名列表。此列表没有固定数量的元素。
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")
评估、声明、让
另一种更糟糕的方法是使用eval
或declare
设置这些值。
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
...
(或者也使用关联数组来存储组名称。)