for制御変数から添え字付き環境変数へのセット

for制御変数から添え字付き環境変数へのセットの話の続き。もちろん、任意の内容を安全にセット出来なれればならない。

set= の左辺のみ2度評価して、右辺は1度しか評価してはいけないわけだが、1文でやるのは前回無理とわかった(実は書いた以上にもいろいろ試行錯誤している)ので、2文以上に分けるしかない。まず思いつくのは、

echo %%A | call set /p SAVE%%J%%=

だが、これでは何もセットされなかった(SAVE%J%は未定義状態)。
何が悪いのか切り分けのために、テストとして、

echo %%A | call set /p SAVE%%J%%=
set SAVE

echo %%A | ( call set /p SAVE%%J%%=&set SAVE)

をやってみると、環境変数にセットはされるもののその値を次の行で参照できないと言うことがわかる。おそらく、パイプの各要素がサブシェルのCMD.EXEで実行されて親のCMD.EXEの環境変数に反映されないためと思われる。

echo %%A>FILE
call set /p SAVE%%J%%=< FILE

と、ファイルを経由すれば問題はない。ただ、あまり中間ファイルは使いたくない。

後は、複合文中での環境変数参照の記事での、(4)の方法である。

for /f %%B in ('echo SAVE%%J%%') do set %%B=%%A

これはうまく行く。ただし、(' ') の中もサブシェルで実行されるため、tail コマンドで使うと、読み込んだファイル1行ごとにサブシェル起動が入るため遅そうである。