我怎样才能让这段代码的工作?
#!/bin/bash
ARRAYNAME='FRUITS'
FRUITS=( APPLE BANANA ORANGE )
for FRUIT in ${!ARRAYNAME[@]}
do
echo ${FRUIT}
done
此代码:
echo ${!ARRAYNAME[0]}
打印苹果 。 我tryng做类似,但与“[@]”的阵列上重复的东西。
提前致谢,
我怎样才能让这段代码的工作?
#!/bin/bash
ARRAYNAME='FRUITS'
FRUITS=( APPLE BANANA ORANGE )
for FRUIT in ${!ARRAYNAME[@]}
do
echo ${FRUIT}
done
此代码:
echo ${!ARRAYNAME[0]}
打印苹果 。 我tryng做类似,但与“[@]”的阵列上重复的东西。
提前致谢,
${!ARRAYNAME[@]}
的意思是“指数ARRAYNAME
”。 正如指出的bash手册页 ,因为ARRAYNAME
设置,但作为一个字符串,而不是一个数组,则返回0
。
下面是一个使用的解决方案eval
。
#!/usr/bin/env bash
ARRAYNAME='FRUITS'
FRUITS=( APPLE BANANA ORANGE )
eval array=\( \${${ARRAYNAME}[@]} \)
for fruit in "${array[@]}"; do
echo ${fruit}
done
什么原先尝试做的是创造一个间接引用 。 这些都是在bash版本2中引入并打算在很大程度上取代了需要eval
试图实现在壳反射般的行为时。
你有什么用使用数组间接引用时做的是包括[@]
在你的猜测在变量名:
#!/usr/bin/env bash
ARRAYNAME='FRUITS'
FRUITS=( APPLE BANANA ORANGE )
array="${ARRAYNAME}[@]"
for fruit in "${!array}"; do
echo $fruit
done
所有这一切说,这是一件事在这个简单的例子来使用间接引用,但正如丹尼斯威廉姆森提供的链接表示,你应该犹豫在真实世界的脚本来使用它们。 他们所有,但保证让你的代码比必要更多的混乱。 通常你可以得到你所需要的关联数组的功能。
这里有一个办法做到这一点不EVAL。
见招击#2描述如下: http://mywiki.wooledge.org/BashFAQ/006
似乎在bash 3和多达工作。
#!/bin/bash
ARRAYNAME='FRUITS'
tmp=$ARRAYNAME[@]
FRUITS=( APPLE BANANA ORANGE "STAR FRUIT" )
for FRUIT in "${!tmp}"
do
echo "${FRUIT}"
done
下面是示出如何通过参考一个函数来传递阵列的更现实的例子:
pretty_print_array () {
local arrayname=$1
local tmp=$arrayname[@]
local array=( "${!tmp}" )
local FS=', ' # Field seperator
local var
# Print each element enclosed in quotes and separated by $FS
printf -v var "\"%s\"$FS" "${array[@]}"
# Chop trailing $FS
var=${var%$FS}
echo "$arrayname=($var)"
}
FRUITS=( APPLE BANANA ORANGE "STAR FRUIT" )
pretty_print_array FRUITS
# prints FRUITS=("APPLE", "BANANA", "ORANGE", "STAR FRUIT")
eval
执行包含代码的数组元素,即使它们包含,例如,命令置换。 它也改变通过它们的bash解释元字符数组元素。
避免这些问题的工具是declare
参考 ,见man bash
下宣告:
-n给每个名字的属性nameref,使其成为一个名称引用另一个变量。 其它变量由名称的值来定义。 所有参考文献,任务和属性修改名称,除非使用或更改-n属性本身的,是由名称的值引用的变量进行。 所述nameref属性不能被应用到数组变量。
#!/bin/bash
declare -n ARRAYNAME='FRUITS'
FRUITS=(APPLE BANANA ORANGE "BITTER LEMON")
for FRUIT in "${ARRAYNAME[@]}"
do
echo "${FRUIT}"
done
我只是想补充另一种有用的用例。 我在网上搜索解决一个不同的,但相关的问题
ARRAYNAME=( FRUITS VEG )
FRUITS=( APPLE BANANA ORANGE )
VEG=( CARROT CELERY CUCUMBER )
for I in "${ARRAYNAME[@]}"
do
array="${I}[@]"
for fruit in "${!array}"; do
echo $fruit
done
done
尽管简单OP的问题,这些问题的答案将不能扩展为最常见,实际使用情况,即包含空格或应该还没有扩展到文件名通配符数组元素。
FRUITS=( APPLE BANANA ORANGE 'not broken' '*.h')
ARRAYNAME=FRUITS
eval ARRAY=\(\${$ARRAYNAME[@]}\)
$ echo "${ARRAY[4]}"
broken
$ echo "${ARRAY[5]}"
config.h
$
这工作:
FRUITS=( APPLE BANANA ORANGE 'not broken' '*.h')
ARRAYNAME=FRUITS
eval ARRAY="(\"\${$ARRAYNAME[@]}\")"
$ echo "${ARRAY[3]}"
not broken
$ echo "${ARRAY[4]}"
*.h
$
正如你应该使用的习惯, "$@"
不是$@
,总是引用里面( )
数组扩展,除非你想文件名扩展或知道有没有包含空格的数组元素的可能性。
这样做: X=("${Y[@]}")
不这样的: X=(${Y[@]})