回答:
これを試してください:
$ arrayA=(1 2 3)
$ x=A
$ var=array$x[@]
$ echo ${!var}
1 2 3
man bash(パラメータ展開):${parameter} The value of parameter is substituted. The braces are required when parameter is a positional parameter with more than one数字、またはパラメータの後にその名前の一部として解釈されない文字が続く場合。
*パラメータの最初の文字が感嘆符(!)の場合、変数の間接参照のレベルが導入されます。Bashは、残りのパラメーターから形成された変数の値を変数の名前として使用します。次に、この変数が展開され、その値がパラメーター自体の値ではなく、残りの置換で使用されます。これは間接展開と呼ばれます。*これの例外は、以下で説明する$ {!prefix *}および$ {!name [@]}の拡張です。感嘆符は、間接参照を導入するために、左中括弧の直後に続く必要があります。
!前で何をしているのvarですか?それがどのように機能するか、それはグーグルでの歴史の代用であるように見えました、しかし私はそれがここでどのように機能するか見ることができませんでした。
別の回答で指摘されているように間接アクセスを使用できますが、別の方法(kshおよびBash 4.3以降)ではnamerefを使用します。特に配列の場合、namerefを介して配列にインデックスを付けることができ、参照として使用される変数にインデックスを置く必要がないため、これはより便利です。
arr1=(a b c)
arr2=(x y z)
typeset -n p=arr1 # or 'declare -n'
echo "${p[1]}" # prints 'b'
これは間接的なアクセスでは機能しません。
q=arr2
echo "${!q}" # prints 'x', the same as $arr2
echo "${!q[1]}" # doesn't work, it tries to take q[1] as a reference
Cプログラマーが言うように、${!q[1]}ここでqは、配列へのポインターではなく、ポインターの配列であるかのように動作します。
これには多くの試行錯誤が必要でしたが、最終的には機能しました。
Younessからインスピレーションを受けました。しかし、他のすべての答えは私の古いbashを助けませんでした(suse11sp1 [3.2.51(1)-release])
'for'ループが間接配列の拡張を拒否しました。代わりに、それを事前拡張する必要があります。これを使用して、新しい変数名で別の配列を作成します。以下の例は、二重ループを示しています。
THEBIGLOOP=(New_FOO New_BAR)
FOOthings=(1 2 3)
BARthings=(a b c)
for j in ${THEBIGLOOP[*]}
do
TheNewVariable=$(eval echo \${${j#New_}things[@]})
for i in $TheNewVariable
do
echo $j $i" hello"
echo
done
done
#を使用して最初の配列エントリから「New_」を削除し、次に「things」と連結して「FOOthings」を取得しています。\ $ {}にechoとevalを付けて、エラーをスローせずに順番に処理します。これは新しい$()でラップされ、新しい変数名が割り当てられます。
$ Test.sh
New_FOO 1 hello
New_FOO 2 hello
New_FOO 3 hello
New_BAR a hello
New_BAR b hello
New_BAR c hello
アップデート##### 2018/06/07
私は最近、この問題に関するもう1つのスピンを発見しました。作成される変数は実際には配列ではなく、スペースで区切られた文字列です。上記のタスクではこれは問題ありませんでした。「for」が機能するため、配列を読み取らず、展開されてからループされます。以下の抜粋を参照してください。
for VARIABLE in 1 2 3 4 5 .. N
do
command1
command2
commandN
done
しかし、それを配列として使用する必要がありました。このため、もう1つの手順を実行する必要がありました。私はデニス・ウィリアムソンによるコードを逐語的に採用しました。私はそれをテストしました、そしてそれはうまく働きます。
IFS=', ' read -r -a TheNewVariable <<< ${TheNewVariable[@]}
「IFS = '、'」は、あなたの分娩誘発剤を含む変数です。"-a"を指定した "read"は、文字列を切り取り、配列変数にフィードバックします。これは引用符を考慮していませんが、これを管理するための読み取りオプションがいくつかあります。たとえば、不要な-rフラグを削除しました。そこで、この追加と変数の作成を組み合わせました。これにより、データを必要に応じて処理およびアドレス指定できます。
THEBIGLOOP=(New_FOO New_BAR)
FOOthings=(1 2 3)
BARthings=(a b c)
for j in ${THEBIGLOOP[*]}
do
IFS=', ' read -a TheNewVariable <<< $(eval echo \${${j#New_}things[@]})
for i in ${TheNewVariable[@]} #Now have to wrap with {} and expand with @
do
echo $j $i" hello"
echo ${TheNewVariable[$i]} #This would not work in the original code
echo
done
done
ありえない :(
配列が単純な場合は、連想配列を使用します
declare -A array
array[A]="1 2 3"
array[B]="a b c"
残念ながら、配列がもっと複雑な場合(たとえばarray=( "a b" c ))、それは機能しません。次に、目標を達成するための別の方法についてより深く考える必要があります。
これは、動的に名前が付けられた変数を作成する方法です(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[@]}
以下は、動的に名前が付けられた配列を管理するために使用できる関数のグループです(bashバージョン<4.3)。
# Dynamically create an array by name
function arr() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
# The following line can be replaced with 'declare -ag $1=\(\)'
# Note: For some reason when using 'declare -ag $1' without the parentheses will make 'declare -p' fail
eval $1=\(\)
}
# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
eval $1[\$\(\(\${#${1}[@]}\)\)]=\$2
}
# Update an index by position
function arr_set() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
eval ${1}[${2}]=\${3}
}
# Get the array content ${array[@]}
function arr_get() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
eval echo \${${1}[@]}
}
# Get the value stored at a specific index eg. ${array[0]}
function arr_at() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
[[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
local v=$1
local i=$2
local max=$(eval echo \${\#${1}[@]})
# 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() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
local v=${1}
eval echo \${\#${1}[@]}
}
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
以下は、動的に名前が付けられた配列(bashバージョン> = 4.3)を管理するために使用できる関数のグループです。
# Dynamically create an array by name
function arr() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -g -a $1=\(\)
}
# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
r[${#r[@]}]=$2
}
# Update an index by position
function arr_set() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
r[$2]=$3
}
# Get the array content ${array[@]}
function arr_get() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
echo ${r[@]}
}
# Get the value stored at a specific index eg. ${array[0]}
function arr_at() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
[[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
declare -n r=$1
local max=${#r[@]}
# Array has items and index is in range
if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
then
echo ${r[$2]}
fi
}
# Get the value stored at a specific index eg. ${array[0]}
function arr_count() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
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
これらの例の詳細については、Ludvik Jerabekによる「Getting Bashed by Dynamic Arrays」を参照してください。