この質問は何度も要求されましたが、どの方法も効果がありませんでした。変数から配列名を取得した配列を動的にしたいと思います。それでは配列から始めましょう。
#!/bin/bash
i="aaa"
eval ${i}=("1")
明らかにする
./1.sh: line 3: syntax error near unexpected token `('
./1.sh: line 3: `eval ${i}=("1")'
次の結果:
$(eval ${i})=('1')
$(eval echo ${i})=('1')
$(eval "echo ${i}")=('1')
すべてを評価したくなく、配列名だけを評価したいと思います。可能であれば、evalを完全に使用することを避けたいと思います。
答え1
eval
引数として文字列が必要です。引用符なしでは使用できず、(
シェルで特別な意味を持ちます。
i=aaa
eval "$i=(1 2)" # Use a string, $i will expand in double quotes.
echo ${aaa[1]}
declare
代わりに、typeset
次のものを使用することもできますeval
。
declare -a $i='(1 2)'
それでも括弧とスペースを引用する必要があります。
これを完全に防ぐには、eval
値を1つずつ割り当てるだけです。
#! /bin/bash
name=aaa
values=(1 2)
for ((i=0; i<${#values[@]}; ++i)) ; do
read "$name[$i]" <<< "${values[i]}"
done
echo ${aaa[1]}
答え2
を使わずに配列をロードする方法は次のとおりですeval
。構文を使用せずに、( data )
代わりに入力文字列と選択した区切り文字を使用します。例では、次を使用します。|
i=aaa
IFS='|' read -a "$i" <<<"1|2 with spaces"
printf '%s\n' "${aaa[@]}"
出力:
1
2 with spaces
答え3
declare
動的名前と値、および変数間接参照を使用して、その名前に基づいて変数を参照できます。printf '%q'
動的割り当て中に値を使用できるように、「シェルエスケープ」値を助けることができます。
#!/bin/bash
declare -a products=( phone computer )
printf 'Product: %s\n' "${products[@]}"
# Product: phone
# Product: computer
unset products
declare varName='products'
declare -a "${varName}"='( cell\ phone laptop\ computer )'
declare arrayRef="${varName}[@]"
printf 'Product: %s\n' "${!arrayRef}"
# Product: cell phone
# Product: laptop computer
unset "${varName}"
declare -a toCopy=( 'LED TV' '"Smart" car' )
declare -a "${varName}"="( $( printf '%q ' "${toCopy[@]}" ) )"
printf 'Product: %s\n' "${!arrayRef}"
# Product: LED TV
# Product: "Smart" car
unset "${varName}"