配列名から配列の内容を拡張するには? [コピー]

配列名から配列の内容を拡張するには? [コピー]

配列があります

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

bash4.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"'[@]}")'

関連情報