我有一个包含类别名称的数组
categories=( categoryA categoryB categoryC )
每个类别都包含多个产品,这些产品存储在不同的数组中。
categoryA=( productA1 productA2 productA3 )
categoryB=( productB1 productB2 productB3 )
categoryC=( productC1 productC2 productC3 )
我想循环所有产品,所以我写了这段代码:
categories=( categoryA categoryB categoryC )
categoryA=( productA1 productA2 productA3 )
categoryB=( productB1 productB2 productB3 )
categoryC=( productC1 productC2 productC3 )
for category_name in "${categories[@]}"
do
echo $category_name
category=${!category_name}
for product in "${category[@]}"
do
echo -e '\t' $product
done
echo -e '\n'
done
我希望输出为:
CategoryA
ProductA1
ProductA2
ProductA3
CategoryB
ProductB1
ProductB2
ProductB3
CategoryC
ProductC1
ProductC2
ProductC3
但不幸的是,输出是
CategoryA
ProductA1
CategoryB
ProductB1
CategoryC
ProductC1
如何解决这个问题?
答案 0 :(得分:1)
在这种情况下,绝对要 NOT 使用eval
,只需使用declare
动态创建变量,
只需替换
行category=${!category_name}
在你的原始答案中
declare -n category="${category_name}"
上述declare
语法将为变量category
创建category_name
的引用,可以进一步访问该变量以便作为数组进行扩展。
declare -n
是Bash 4.3-alpha
答案 1 :(得分:1)
如果Inian's answer不适合您,因为您使用的是早于4.3的bash版本(引入了对nameref变量的支持),您可以使用以下解决方案:
categories=( categoryA categoryB categoryC )
categoryA=( productA1 productA2 productA3 )
categoryB=( productB1 productB2 productB3 )
categoryC=( productC1 productC2 productC3 )
for category_name in "${categories[@]}"
do
echo $category_name
array_declaration="$(declare -p $category_name)"
# "$array_declaration" expands to the command that can be (safely)
# evaluated to recreate the $category_name variable
# change the variable name in the array declaration and eval it
eval "${array_declaration/#declare -a "$category_name"=/declare -a category=}"
for product in "${category[@]}"
do
echo -e '\t' $product
done
echo -e '\n'
done
请注意,上述代码中对eval
的依赖应该是安全的,因为declare -p
的输出已正确引用。
答案 2 :(得分:0)
我已经找到了解决方案,
而不是category=${!category_name}
,
我可以评估数组eval category=\( \${${category_name}[@]} \)
对于那些感兴趣的人,这里是:
for category_name in "${categories[@]}"
do
echo $category_name
eval category=\( \${${category_name}[@]} \)
for product in "${category[@]}"
do
echo -e '\t' $product
done
echo -e '\n'
done
对于遇到同样挑战的人,以及任何有更优雅解决方案或任何反对意见的人,我会留下问题和答案
更新:出于安全考虑,请检查Inian的响应,如果您使用Bash< 4.3和我一样,检查莱昂的回应是另类