BASH:如何在循环中创建动态数组名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16523581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:24:58  来源:igfitidea点击:

BASH: how to create a dynamic array name in a loop

arraysbashdynamic

提问by Peter Pan

here's what I tried:

这是我尝试过的:

n=0
for i in aaa bbb ccc; do
  array${i}[$n]=$(date "+%N")
  ((++n))
done
n=0
for i in aaa bbb ccc; do
  echo ${array${i}[$n]}
  ((++n))
done

any ideas how to make the dynamic array name work? thanks a lot!

任何想法如何使动态数组名称工作?多谢!

回答by Sir Athos

You can use indirect expansion:

您可以使用间接扩展:

#!/bin/bash

# create the arrays
n=0
for i in aaa bbb ccc; do
    let array$i[$n]=$(date "+%N")
    ((++n))
done

# display what we did
n=0
for i in aaa bbb ccc; do
    var=array$i[$n]
    echo ${!var}
    ((++n))
done

Note that this will only create array variables arrayaaa[0], arraybbb[1]and arrayccc[2], and not(as you might expect) arrayaaa[0], arrayaaa[1], arrayaaa[2], arraybbb[0], arraybbb[1], arraybbb[2], arrayccc[0], arrayccc[1], and arrayccc[2].

请注意,这只会创建数组变量arrayaaa[0]arraybbb[1]arrayccc[2],而不是(如您所料)arrayaaa[0]arrayaaa[1]arrayaaa[2]arraybbb[0]arraybbb[1]arraybbb[2]arrayccc[0]arrayccc[1]arrayccc[2]

回答by NOPx90

This is how you would create a dynamically named variable (bash version < 4.3).

这是创建动态命名变量的方式(bash 版本 < 4.3)。

# Dynamically named array
my_variable_name="dyn_arr_names"
eval $my_variable_name=\(\)

# Adding by index to the array eg. dyn_arr_names[0]="bob"
eval $my_variable_name[0]="bob"

# Adding by pushing onto the array eg. dyn_arr_names+=(robert)
eval $my_variable_name+=\(robert\)

# Print value stored at index indirect
echo ${!my_variable_name[0]}

# Print value stored at index
eval echo ${$my_variable_name[0]}

# Get item count
eval echo ${#$my_variable_name[@]}

Below is a group of functions that can be used to manage dynamically named arrays (bash version < 4.3).

下面是一组可用于管理动态命名数组的函数(bash 版本 < 4.3)。

# Dynamically create an array by name
function arr() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
     # The following line can be replaced with 'declare -ag =\(\)'
     # Note: For some reason when using 'declare -ag ' without the parentheses will make 'declare -p' fail
    eval =\(\)
}

# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() { 
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    eval [$\(\(${#[@]}\)\)]=$2
}

# Update an index by position
function arr_set() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    eval []=${3}
}

# Get the array content ${array[@]}
function arr_get() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    eval echo ${[@]}
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_at() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    [[ ! "" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
    local v=
    local i=
    local max=$(eval echo ${\#[@]})
    # Array has items and index is in range
    if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
    then 
        eval echo ${$v[$i]}
    fi
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_count() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    local v=
    eval echo ${\#[@]}
}



array_names=(bob jane dick)

for name in "${array_names[@]}"
do
    arr dyn_$name
done

echo "Arrays Created"
declare -a | grep "a dyn_"

# Insert three items per array
for name in "${array_names[@]}"
do
    echo "Inserting dyn_$name abc"
    arr_insert dyn_$name "abc"
    echo "Inserting dyn_$name def"
    arr_insert dyn_$name "def"
    echo "Inserting dyn_$name ghi"
    arr_insert dyn_$name "ghi"
done

for name in "${array_names[@]}"
do
    echo "Setting dyn_$name[0]=first"
    arr_set dyn_$name 0 "first"
    echo "Setting dyn_$name[2]=third"
    arr_set dyn_$name 2 "third"
done 

declare -a | grep "a dyn_"

for name in "${array_names[@]}"
do
    arr_get dyn_$name
done


for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name by index"
    # Print by index
    for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
    do
        echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"

    done
done

for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name"
    for n in $(arr_get dyn_$name)
    do
        echo $n
    done
done

Below is a group of functions that can be used to manage dynamically named arrays (bash version >= 4.3).

下面是一组可用于管理动态命名数组的函数(bash 版本 >= 4.3)。

# Dynamically create an array by name
function arr() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -g -a =\(\)   
}

# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() { 
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=
    r[${#r[@]}]=
}

# Update an index by position
function arr_set() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r= 
    r[]=
}

# Get the array content ${array[@]}
function arr_get() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r= 
    echo ${r[@]}
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_at() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    [[ ! "" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
    declare -n r= 
    local max=${#r[@]}
    # Array has items and index is in range
    if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
    then 
        echo ${r[]}
    fi
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_count() {
    [[ ! "" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
    declare -p "" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=
    echo ${#r[@]}
}



array_names=(bob jane dick)

for name in "${array_names[@]}"
do
    arr dyn_$name
done

echo "Arrays Created"
declare -a | grep "a dyn_"

# Insert three items per array
for name in "${array_names[@]}"
do
    echo "Inserting dyn_$name abc"
    arr_insert dyn_$name "abc"
    echo "Inserting dyn_$name def"
    arr_insert dyn_$name "def"
    echo "Inserting dyn_$name ghi"
    arr_insert dyn_$name "ghi"
done

for name in "${array_names[@]}"
do
    echo "Setting dyn_$name[0]=first"
    arr_set dyn_$name 0 "first"
    echo "Setting dyn_$name[2]=third"
    arr_set dyn_$name 2 "third"
done 

declare -a | grep 'a dyn_'

for name in "${array_names[@]}"
do
    arr_get dyn_$name
done


for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name by index"
    # Print by index
    for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
    do
        echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"

    done
done

for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name"
    for n in $(arr_get dyn_$name)
    do
        echo $n
    done
done

For more details on these examples visit Getting Bashed by Dynamic Arrays by Ludvik Jerabek

有关这些示例的更多详细信息,请访问由 Ludvik Jerabek 编写的动态数组

回答by anubhava

Take refuge of eval:

躲避评估:

n=0
for i in aaa bbb ccc; do
  eval "array${i}[$n]=$(date "+%N")"
  ((++n))
done