arrays - 在 BASH 中对另一个数组进行迭代期间使用变量动态命名数组

标签 arrays bash associative-array

我有一个数组

FIRST_ARRAY=(NEWYORK CALIFORNIA TEXAS)

接受状态的脚本可以返回该状态下的城市

例如,将返回以下内容:

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 $1 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")'

关于arrays - 在 BASH 中对另一个数组进行迭代期间使用变量动态命名数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38553371/

相关文章:

bash - 强制 Bash 脚本等待等待输入的 Perl 脚本

PHP: undefined index !但它被定义

arrays - 递归消除元胞数组中的数字

bash - 在 bash 脚本中,是否可以将由后台进程计算的值分配给变量?

arrays - 火车站到中心的距离等于 N 英里

bash - 如何使用 Bash 创建文件的副本,在扩展名前添加一个额外的后缀?

php - 我可以将关联数组发送到包含的 Twig 模板中吗?

bash 4.x assoc 数组在接收函数中丢失键

arrays - 使用 Ruby 按组自定义排序数组

PHP - 将 foreach 转换为数组