配列があります
declare -a arr0=("'1 2 3'" "'4 5 6'")
そして変数
x=0
次に、配列名で新しい変数を作成します。
tmp="arr$x"
arr0
この変数の内容を次のように拡張したいと思います。tmp
newArr=( "${!tmp}" )
newArr
たとえば、索引付けなどを使用して通常の配列のように使用されます。
しかし、今印刷しようとすると、次のようになります。
$ echo ${newArr[@]}
'1 2 3'
最初の要素だけが保存されますが、どのように変更するのかわかりません。
newArr
私もこのようにしてみました
newArr=( "${!tmp[@]}" )
しかし、もっと悪いのは、ゼロだけが印刷されるということです。
$ echo ${newArr[@]}
0
もしそうなら、配列の名前が別の変数に格納されている場合、配列の使用方法を知っていますか?
答え1
これは可能です評価する:
$ declare -a array=( 1 2 3 4 )
$ echo "${array[@]}"
1 2 3 4
$ p=ay
$ tmp=arr$p
$ echo "$tmp"
array
$ echo "\${${tmp}[@]}"
${array[@]}
$ echo "newarray=(\"\${${tmp}[@]}\")"
newarray=("${array[@]}")
$ eval "newarray=(\"\${${tmp}[@]}\")"
$ echo "${newarray[@]}"
1 2 3 4
$
echoで始まるコマンドは参照用であり、evalは危険です。
上記は希少配列の配列インデックスを保持しません。
答え2
間接拡張にはいくつかの例外があり、配列で!を使用することは例外の1つです。
メンズバッシュから:
パラメーターの最初の文字が感嘆符(!)の場合、1段階変数間接指定が導入されます。 Bash は、残りの引数で構成される変数値を変数名として使用します。次に、その変数を展開し、引数自体の値ではなく、残りの置換にその値を使用します。これを間接拡張といいます。
下記の ${!prefix*} と ${!name[@]} の拡張は例外です。 ${!prefix*} はプレフィックスの名前と一致します。 IFS特殊変数の最初の文字で区切られた名前は、プレフィックスで始まる変数名に展開されます。
で述べたようにBASH よくある質問 06、1つの解決策は次のとおりです。
arrA=("AA" "2" "4")
echo -e "array arrA contains: \c" && declare -p arrA
ref=arrA;
tmp=${ref}[@] #this can be adjusted to [1] , [2] etc to refer to particular array items
echo "Indirect Expansion Printing: ${!tmp}"
#Output
array arrA contains: declare -a arrA='([0]="AA" [1]="2" [2]="4")'
Indirect Expansion Printing: AA 2 4
答え3
bash
4.3では、同様のnamerefのサポートが追加されましたksh93
。
したがって、bash-4.3以降では、次のことができます。
a0[5]=whatever
x=0
typeset -n var="a$x"
printf '%s\n' "${var[5]}"
しかし、これは引用する(ポインタ、コピーではない)変数に名前、変数ではない(関数のローカル変数など、異なるコンテキストで同じ名前を持つ複数の変数がある場合、違いは重要です。)
bash
配列とその厄介なデザインをコピーしますksh
。配列をコピーするbash
のは難しいです。以下のヘルパー機能を使用できます。
copy_array() { # Args: <src_array_name> <dst_array_name>
eval '
local i
'"$2"'=()
for i in "${!'"$1"'[@]}"; do
'"$2"'[$i]=${'"$1"'[$i]}
done'
}
たとえば、次のように使用されます。
$ a0[5]=123
$ x=0
$ copy_array "a$x" var
$ typeset -p var
declare -a var=([5]="123")
ksh
(そしてbash
コピーされたksh
)は配列を持つ唯一のシェルです。足りない(またはキーが正の整数に制限される連想配列) (また、インデックスが 1 ではなく 0 から始まる、または直感的に要素に拡張されず、$array
インデックス 0 に拡張される唯一の配列).他のシェルを使用する方がはるかに簡単です。
rc
:array_copy = $array
fish
:set array_copy = $array
csh
:set array_copy = ($array:q)
zsh
またはyash
:array_copy=("${array[@]}"}
間接コピー($var
ソース配列名を含む)の場合:
rc
:eval array_copy = '$'$var
fish
:eval set array_copy \$$var
csh
:eval "set array_copy = (\$${var}:q)"
zsh
:array_copy=("${(@P)var}")
yash
(またはzsh
):eval 'array_copy=("${'"$var"'[@]}")'