変数を間接的に参照する(シェルスクリプト)

課題

ある変数Aに別の変数Bの変数名を格納し、変数Aを通して変数Bの値にアクセスしたい。

解決策

eval コマンドを利用する。eval は shell による評価を再実行するためのコマンドである。

単純なケースを例示する。

nameA=value
nameB=nameA

echo ${nameB}         # --> nameA
eval echo \$${nameB}  # --> value

nameB の値として nameA という文字列が格納されている。これは別の変数の変数名だ。単純に nameB の値を出力すると当然 nameA が表示される。一方で、eval の行を評価すると、本記事の主旨のように、nameA の値(= value)が表示される。

eval の行の評価の過程を以下に示す。

eval echo \$${nameB}
↓ shellによる評価
eval echo $nameA
↓ evalによる評価(shellによるニ度目の評価)
echo value
↓
value(標準出力へ出力)

ちなみに「\$」の表記は、「\」により「$」の特殊な意味(shell による変数展開)を無効にすることを意味する。eval による評価(shell による二度目の評価)の際に、もう一度変数展開を実行するために、「$」の記号を残す必要があるので、このような操作が必要になっている。


変数の間接参照の応用例のひとつとして、配列的な操作が可能となる。変数名の一部として配列インデックスの情報を含む複数の変数が存在し、そのインデックス部分が変化すると考えれば良い。以下に例示する。

var1=a
var2=b
var3=c

for i in $(seq 1 3)
do
  eval echo \$var$i   # --> a b c
done

所感

eval はシェルスクリプトの可能性を大きく広げるコマンドである。しかしご利用は計画的に。多用するとスクリプトの解読が困難になる可能性がある。未来の自分に迷惑をかけないで。