Bashシェルスクリプトで変数の値を使って別の変数を参照する方法

Bash, Linux

はじめに

Bashで変数の値を使って、別の変数を参照するにはどう書けばよいでしょう?

少々説明がくどいですが、PHPや他の言語では普通にできるコードを書けるか?というお話です。

実際にPHPで書く場合とBashで書く場合を見ていきます。

検証環境

$ uname -moi
x86_64 MacBookPro11,4 Darwin

$ bash -version | head -n 1
GNU bash, バージョン 5.0.11(1)-release (x86_64-apple-darwin18.6.0)

PHPのコードサンプル

以下のように $var1 , $var2 , $var3 の3つの変数を、ループを使って参照する場合には以下のようなコードで実現できます。

<?php

$var1 = '111';
$var2 = '222';
$var3 = '333';

for ($i = 1; $i <= 3; ++$i) {
    $varName = "var${i}";
    echo "$i = ${$varName}" . PHP_EOL;
}
$ php test.php
1 = 111
2 = 222
3 = 333

Bashのコードサンプル

方法は2つあります。

1. 変数名の前に ! を記述する

先のPHPのサンプルコードと同じように、 var1 , var2 , var3 の3つの変数を、ループを使って参照する場合には以下のようなコードで実現できます。

ポイントは ! を付与する点ですね。

通常の変数参照は ${VAR} となりますが、 変数 VAR の値を変数名として参照する場合${!VAR} のように記述します。

#!/usr/bin/env bash

var1="111"
var2="222"
var3="333"

for ((i = 1; i <= 3; i++)); do
  var_name="var${i}"
  echo "var${i} = ${!var_name}"
done
$ bash test.sh
var1 = 111
var2 = 222
var3 = 333

2. eval コマンドを利用する

eval コマンドを使って実現する方法もあります。

一度変数展開した文字列を作成し、その後 eval コマンドに渡して再度変数展開を行います。

#!/usr/bin/env bash

var1="111"
var2="222"
var3="333"

for ((i = 1; i <= 3; i++)); do
  var_name="var${i}"

  # どんなコマンドが実行されるのかな?
  echo eval "echo \"var${i} = \${${var_name}}\""

  # 実際にコマンドを実行してみる
  eval "echo \"var${i} = \${${var_name}}\""
done
$ bash test.sh
eval echo var1 = ${var1}
var1 = 111
eval echo var2 = ${var2}
var2 = 222
eval echo var3 = ${var3}
var3 = 333

ひとこと

なかなか利用することはないです。
僕自身も今回初めて記述しました。

多用するとコードも読みにくくなりますしね。

Bash, Linux