在 BASH 中对另一个数组进行迭代期间使用变量动态命名数组
Dynamically name array with variable during iteration over another array in BASH
我有一个数组
FIRST_ARRAY=(NEWYORK CALIFORNIA TEXAS)
接受一个州的脚本可以 return 该州的城市
例如,以下将 return:
user@localhost:~$ search NEWYORK cities
newyorkcity
buffalo
albany
user@localhost:~$ search CALIFORNIA cities
sanfrancisco
paloalto
losangeles
user@localhost:~$ search TEXAS cities
houston
dallas
austin
我想遍历 FIRST_ARRAY
for state in ${FIRST_ARRAY[@]}
do
cities=`search ${FIRST_ARRAY[state]} cities`
ARRAY_$state=($cities}
done
最后我希望创建以下数组,它们将包含以下值
ARRAY_NEWYORK=(newyorkcity buffalo albany)
ARRAY_CALIFORNIA=(sanfrancisco paloalto losangeles)
ARRAY_TEXAS=(houston dallas austin)
如果这可行,那么例如,我希望能够通过以下方式调用动态创建的数组来访问 austin
echo ${ARRAY_TEXAS[2]}
谢谢!
在 bash 4.0 或更高版本上,readarray
/ mapfile
可用,以下是简洁正确的实现:
for state in "${FIRST_ARRAY[@]}"; do
readarray -t "ARRAY_$state" < <(search "$state" cities)
done
在 bash 4.3 中,可以使用安全的直译代码:
for state in "${FIRST_ARRAY[@]}"; do
readarray -t cities < <(search "$state" cities)
# make "dest" a namevar -- an alias -- for your intended destination
# skip to next state if current state name is invalid
# otherwise we could be assigning to an utterly different "dest"
declare -n dest="ARRAY_$state" || continue
# assign to that namevar
dest=( "$cities" )
# and discard it
unset -n dest
done
在 bash 3.x 中,安全地执行此操作需要一些 printf %q
魔法来准备要由 eval
:
解析的内容
for state in "${FIRST_ARRAY[@]}"; do
# why this, and not array=( $cities )? Try a city with spaces in its name.
# or look at what happens when you have a "city name" that's a wildcard.
cities=( )
while read -r city; do
cities+=( "$city" )
done < <(search "$state" cities)
# generate eval-safe replacement for the cities array
printf -v cities_str '%q ' "${cities[@]}"
# extra paranoia: make sure we fail with a parse error rather than doing something
# unexpected if the state name is not a valid shell variable
printf -v eval_str 'ARRAY_%q=( %s )' "$state" "$cities_str"
eval "$eval_str" # and evaluate that
done
原始问题没有提供 search
的实现来使答案可测试。对于这个答案,我使用以下内容:
search() {
case in
NEWYORK) printf '%s\n' newyorkcity buffalo albany ;;
CALIFORNIA) printf '%s\n' sanfrancisco paloalto losangeles ;;
TEXAS) printf '%s\n' houston dallas austin ;;
esac
}
根据上面的定义,可以验证结果如下:
$ declare -p ARRAY_NEWYORK ARRAY_CALIFORNIA ARRAY_TEXAS
declare -a ARRAY_NEWYORK='([0]="newyorkcity" [1]="buffalo" [2]="albany")'
declare -a ARRAY_CALIFORNIA='([0]="sanfrancisco" [1]="paloalto" [2]="losangeles")'
declare -a ARRAY_TEXAS='([0]="houston" [1]="dallas" [2]="austin")'
我有一个数组
FIRST_ARRAY=(NEWYORK CALIFORNIA TEXAS)
接受一个州的脚本可以 return 该州的城市
例如,以下将 return:
user@localhost:~$ search NEWYORK cities
newyorkcity
buffalo
albany
user@localhost:~$ search CALIFORNIA cities
sanfrancisco
paloalto
losangeles
user@localhost:~$ search TEXAS cities
houston
dallas
austin
我想遍历 FIRST_ARRAY
for state in ${FIRST_ARRAY[@]}
do
cities=`search ${FIRST_ARRAY[state]} cities`
ARRAY_$state=($cities}
done
最后我希望创建以下数组,它们将包含以下值
ARRAY_NEWYORK=(newyorkcity buffalo albany)
ARRAY_CALIFORNIA=(sanfrancisco paloalto losangeles)
ARRAY_TEXAS=(houston dallas austin)
如果这可行,那么例如,我希望能够通过以下方式调用动态创建的数组来访问 austin
echo ${ARRAY_TEXAS[2]}
谢谢!
在 bash 4.0 或更高版本上,readarray
/ mapfile
可用,以下是简洁正确的实现:
for state in "${FIRST_ARRAY[@]}"; do
readarray -t "ARRAY_$state" < <(search "$state" cities)
done
在 bash 4.3 中,可以使用安全的直译代码:
for state in "${FIRST_ARRAY[@]}"; do
readarray -t cities < <(search "$state" cities)
# make "dest" a namevar -- an alias -- for your intended destination
# skip to next state if current state name is invalid
# otherwise we could be assigning to an utterly different "dest"
declare -n dest="ARRAY_$state" || continue
# assign to that namevar
dest=( "$cities" )
# and discard it
unset -n dest
done
在 bash 3.x 中,安全地执行此操作需要一些 printf %q
魔法来准备要由 eval
:
for state in "${FIRST_ARRAY[@]}"; do
# why this, and not array=( $cities )? Try a city with spaces in its name.
# or look at what happens when you have a "city name" that's a wildcard.
cities=( )
while read -r city; do
cities+=( "$city" )
done < <(search "$state" cities)
# generate eval-safe replacement for the cities array
printf -v cities_str '%q ' "${cities[@]}"
# extra paranoia: make sure we fail with a parse error rather than doing something
# unexpected if the state name is not a valid shell variable
printf -v eval_str 'ARRAY_%q=( %s )' "$state" "$cities_str"
eval "$eval_str" # and evaluate that
done
原始问题没有提供 search
的实现来使答案可测试。对于这个答案,我使用以下内容:
search() {
case in
NEWYORK) printf '%s\n' newyorkcity buffalo albany ;;
CALIFORNIA) printf '%s\n' sanfrancisco paloalto losangeles ;;
TEXAS) printf '%s\n' houston dallas austin ;;
esac
}
根据上面的定义,可以验证结果如下:
$ declare -p ARRAY_NEWYORK ARRAY_CALIFORNIA ARRAY_TEXAS
declare -a ARRAY_NEWYORK='([0]="newyorkcity" [1]="buffalo" [2]="albany")'
declare -a ARRAY_CALIFORNIA='([0]="sanfrancisco" [1]="paloalto" [2]="losangeles")'
declare -a ARRAY_TEXAS='([0]="houston" [1]="dallas" [2]="austin")'