バッチファイルで配列を使う(環境変数を使って配列変数風に使う)方法について

このはてなダイアリーでは自動的に各エントリーの下にリンク元が表示されます。簡易的なアクセスログみたいなもんですが、最近「バッチファイル 配列」というキーワードで見に来ている人が多いことが判明しました。

つまり、バッチファイルで配列変数を使いたい、使い方を知りたいということですね。

結論から言うと、配列変数そのものはバッチファイルにはありません。
しかし配列変数風のものを作って使うことはできます。

まずは配列変数を実現している風に見えるサンプルから。

手っ取り早く、配列変数風のものを使ったサンプルをお見せします。

:--------------------------------------------sample.bat
echo off
for /L %%i in (1,1,10) do set x[%%i]=%%i

echo x[1]=%x[1]%
echo x[8]=%x[8]%
echo.
set x
echo.
set p=4
call echo call echo の場合 --- x[4]=%%x[%p%]%%
for /L %%i in (1,1,10) do (
   call echo %%x[%%i]%%
)

setlocal ENABLEDELAYEDEXPANSION
echo setlocalの場合 --- x[4]=!x[%p%]!
for /L %%i in (1,1,10) do (
   echo !x[%%i]!
)
echo.
set sum=0

for /L %%i in (1,1,10) do (
   if %%i == 5 call set ans5=%%x[%%i]%%
   if %%i == 7 set ans7=!x[%%i]!
   call set /a sum = sum + %%x[%%i]%%
)

echo ans5=%ans5%
echo ans7=%ans7%
echo sum=%sum%


何となく判ってきましたか?
要は、“変数名[数字]”という環境変数名を使っているだけです。そう、"[" 数字 "]"は添え字ではなくあくまで環境変数名の一部です。

配列変数風の配列的な使い方って?

なぜ配列を使いたいかというと、配列というのは添え字の中の数値を変数にして、ループしたり参照したりしたいわけです。
普通の言語の感覚でしたら、添え字の中を変数にしてもそのまま

echo x[i]

と表示したり、

set a=x[i]

という風に代入したりできますよね(この場合iが変数)。バッチは環境変数を%i%という風に"%"でくくって参照するので、同じように考えて

echo %x[%i%]%

set a=%x[%i%]%

などと書いて上手く動かなくて悩むわけです。
じゃあどう書けばいいか。以下にまとめます。

配列変数風書き方のまとめ

(添え字に使う環境変数をiとします。あらかじめ set i=1 などが実行されている。)


■添え字の数値が固定の場合 〜 つまりこれはただの環境変数です。
配列への代入     set x[1]=sample
配列の表示      echo %x[1]%
配列を他の変数へ代入 set ans=%x[1]%


■添え字に変数を使いたい場合 〜 call echo , call set を使う場合
配列への代入     set x[%i%]=sample
配列の表示      call echo %%x[%i%]%%
配列を他の変数へ代入 call set ans=%%x[%i%]%%

どういう理屈か説明しますと、
(1)call echo %%x[%i%]%% の行が評価される。%%→%、%i%→1(環境変数iの中身)に置き換えられる。
(2)call echo %x[1]% としてcall文が実行され組み込みコマンドのechoが子プロセスで実行される(らしい)。
(3)結果として、echo %x[1]% という行が評価されて、環境変数x[1]の中身が表示される。
ということになります。


■添え字に変数を使いたい場合 〜 setlocal ENABLEDELAYEDEXPANSION を使う場合
あらかじめバッチの先頭(途中でも良い)で
setlocal ENABLEDELAYEDEXPANSION
と宣言しておきます。その後以下のように記述します。

配列への代入     set x[%i%]=sample
配列の表示      echo !x[%i%]!
配列を他の変数へ代入 set ans=!x[%i%]!

以上まとめ終わり。

call set,call echo を使うか、setlocal ENABLEDELAYEDEXPANSIONを使うかは好みで決めてください:-)

余談

 添え字の中に使う環境変数の中身は数値である必要はありません。文字列でもかまいません。なぜなら数字であろうと文字列であろうと環境変数名の一部だからです。上手く使えば連想配列のように使えます。
 また、添え字の"[" "]"が無くてもかまいません。区切りをわかりやすくするために使っているだけです。使わないと特にcall set 〜を使った時に"%%x%i%%%"などと%が続いてわかりにくいでしょう(参考エントリ→Yahoo!知恵袋(バッチファイルで反復処理) バッチで配列変数のような添え字を環境変数で使う - バッチもん研究所 blog)。

わかんなかったら、コメント欄でご質問ください。質問大歓迎!