在 bash 中动态创建数组,并以变量作为数组名称

在 bash 中动态创建数组,并以变量作为数组名称

这个问题已经被问过好几次了,但是没有一个方法有效。我想动态创建数组,其数组名称取自变量。所以现在我们只从一个数组开始:

#!/bin/bash
i="aaa"
eval ${i}=("1")

结果是

./1.sh: line 3: syntax error near unexpected token `('
./1.sh: line 3: `eval ${i}=("1")'

与以下结果相同:

$(eval ${i})=('1')
$(eval echo ${i})=('1')
$(eval "echo ${i}")=('1')

我不想评估所有内容,只想评估数组名称。如果可能的话我想完全避免使用 eval

答案1

eval需要一个字符串作为参数。不能使用(不带引号的,它在 shell 中有特殊的含义。

i=aaa
eval "$i=(1 2)"  # Use a string, $i will expand in double quotes.
echo ${aaa[1]}

您还可以使用declareortypeset代替eval

declare -a $i='(1 2)'

您仍然需要引用括号和空格。

为了eval完全避免,可以一一赋值:

#! /bin/bash
name=aaa
values=(1 2)
for ((i=0; i<${#values[@]}; ++i)) ; do
    read "$name[$i]" <<< "${values[i]}"
done
echo ${aaa[1]}

答案2

这是一种不使用 来加载数组的方法eval。它不使用( data )构造 - 相反,它使用输入字符串和您选择的分隔符 - 该示例使用|

i=aaa
IFS='|' read -a "$i" <<<"1|2   with spaces"
printf '%s\n' "${aaa[@]}"

输出:

1
2   with spaces

答案3

您可以使用declare动态名称和值以及变量间接来根据变量的名称来引用变量。 printf '%q'可以帮助您“外壳转义”值,以便可以在动态分配期间使用它们。

#!/bin/bash
declare -a products=( phone computer )
printf 'Product: %s\n' "${products[@]}"
# Product: phone
# Product: computer
unset products

declare varName='products'
declare -a "${varName}"='( cell\ phone laptop\ computer )'
declare arrayRef="${varName}[@]"
printf 'Product: %s\n' "${!arrayRef}"
# Product: cell phone
# Product: laptop computer
unset "${varName}"

declare -a toCopy=( 'LED TV' '"Smart" car' )
declare -a "${varName}"="( $( printf '%q ' "${toCopy[@]}" ) )"
printf 'Product: %s\n' "${!arrayRef}"
# Product: LED TV
# Product: "Smart" car
unset "${varName}"

相关内容