Neu*_*ino 20 bash scripting indirection
如何使此代码有效?
#!/bin/bash
ARRAYNAME='FRUITS'
FRUITS=( APPLE BANANA ORANGE )
for FRUIT in ${!ARRAYNAME[@]}
do
echo ${FRUIT}
done
Run Code Online (Sandbox Code Playgroud)
这段代码:
echo ${!ARRAYNAME[0]}
Run Code Online (Sandbox Code Playgroud)
打印APPLE.我尝试做类似的事情,但用"[@]"迭代数组.
提前致谢,
Tim*_*ote 28
${!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
Run Code Online (Sandbox Code Playgroud)
您最初尝试做的是创建间接参考.这些是在bash版本2中引入的,并且在很大程度上取代了eval在shell中尝试实现类似反射的行为时的需要.
在对数组使用间接引用时,您需要做的是包含[@]对变量名称的猜测:
#!/usr/bin/env bash
ARRAYNAME='FRUITS'
FRUITS=( APPLE BANANA ORANGE )
array="${ARRAYNAME}[@]"
for fruit in "${!array}"; do
echo $fruit
done
Run Code Online (Sandbox Code Playgroud)
总而言之,在这个简单的例子中使用间接引用是一回事,但是,正如Dennis Williamson提供的链接所示,你应该对在真实世界的脚本中使用它们犹豫不决.它们几乎可以保证使您的代码比必要的更令人困惑.通常,您可以使用关联数组获得所需的功能.
Rob*_*ade 13
这是一种没有eval的方法.
请参阅此处描述的Bash技巧#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
Run Code Online (Sandbox Code Playgroud)
这是一个更现实的例子,展示了如何通过引用函数传递数组:
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")
Run Code Online (Sandbox Code Playgroud)
eval执行包含数组元素的代码,即使它们包含,例如,命令替换。它还通过解释其中的 bash 元字符来更改数组元素。
避免这些问题的工具是declare reference,请参阅man bash下面的声明:
-n 为每个名称赋予 nameref 属性,使其成为对另一个变量的名称引用。另一个变量由 name 的值定义。除了使用或更改 -n 属性本身的那些引用、赋值和属性修改之外,所有对 name 的引用、赋值和属性修改都是在 name 值引用的变量上执行的。nameref 属性不能应用于数组变量。
#!/bin/bash
declare -n ARRAYNAME='FRUITS'
FRUITS=(APPLE BANANA ORANGE "BITTER LEMON")
for FRUIT in "${ARRAYNAME[@]}"
do
echo "${FRUIT}"
done
Run Code Online (Sandbox Code Playgroud)
这个答案来得很晚,但我想有比目前提出的方法更干净的方法(尊重他们的作者)。
这是关于使用/ bash 内置-n选项的。(有关更多信息,请在 bash 中输入)。declarelocalhelp declare
那么我们开始吧:
ARRAYNAME='FRUITS';
FRUITS=(APPLE BANANA ORANGE);
# This is the critical addition. With help of option `-n` we declare
# variable `fruits` as indirect reference to another variable. Anytime
# we refer to ${fruits} we would actually refer to a variable whose
# name is stored in `fruits` variable:
declare -n fruits="${ARRAYNAME}";
# Here we use ${fruits} as ordinary variable, but in reality it refers
# to `FRUITS` variable:
for FRUIT in ${fruits[@]}; do
echo "${FRUIT}";
done;
Run Code Online (Sandbox Code Playgroud)
结果是:
APPLE
BANANA
ORANGE
Run Code Online (Sandbox Code Playgroud)