この記事では、遅延環境変数展開の仕組みと使用方法について紹介します。
遅延環境変数展開とは
バッチファイルを書いているとき、ループ内で変数の値を更新し、その更新された値を即座に使用したい場合があります。しかし、通常の変数展開では、ループ内で変数に行った変更が反映されないという問題に直面します。この問題を解決するために、Windowsのバッチ処理では「遅延環境変数展開」という機能が用意されています。
通常の環境変数展開との違い
通常の変数は %変数名% の形式で参照します。しかし、この方法ではループや条件分岐の中で変数の値を更新しても、そのブロック内で変数を参照した場合、更新される前の値が使用されます。これは、変数の展開がバッチファイルが実行されるときや、forループが開始される際に一度だけ行われるためです。
一方で、遅延環境変数展開は !変数名! の形式で参照します。この記述方法を使用することにより、ループや条件分岐の中で変数の値を更新したとしても、更新した値を即座に使用することが可能になります。
遅延環境変数展開が必要なケース
forループ内で更新した変数の内容を使用したい場合、遅延環境変数展開が必要です。
遅延環境変数展開を使用するには、まずsetlocalコマンドとともにEnableDelayedExpansionオプションを指定して、この機能を有効にする必要があります。そして、遅延展開する変数は !変数名! の形式で参照します。
@echo off
setlocal EnableDelayedExpansion
rem 1~5のループ
for /l %%i in (1,1,5) do (
set var=%%i
echo !var!
)
endlocal
pause
実行結果
1
2
3
4
5
続行するには何かキーを押してください . . .
この例では、counter変数がループの各繰り返しで正しくインクリメントされ、その新しい値が即座に反映されていることがわかります。
試しに遅延環境変数展開を外してみる
@echo off
setlocal
rem 1~5のループ
for /l %%i in (1,1,5) do (
set var=%%i
echo %var%
)
endlocal
pause
実行結果
ECHO は <OFF> です。
ECHO は <OFF> です。
ECHO は <OFF> です。
ECHO は <OFF> です。
ECHO は <OFF> です。
続行するには何かキーを押してください . . .
このケースの場合、forループに入るタイミングで、まだ変数 var が定義されていないため、変数 varは存在しないものと扱われ、「echo %var%」が「echo」と解釈されたと思われます。
遅延環境変数展開が不要なケース
gotoコマンドでループを実現する場合、gotoでジャンプする際に変数展開が行われるようです。この場合は、EnableDelayedExpansionが無くても、ループ内で更新した変数の内容を使用できます。
ただし、複雑な処理においては、gotoを使用するループであっても遅延環境変数展開が必要なケースもあるかもしれません。ループ内で変数の値が更新されない現象が発生する場合は、遅延環境変数展開の使用を検討する必要がありそうです。
@echo off
setlocal
set /a counter=0
:loop
if %counter% LSS 5 (
echo %counter%
set /a counter=%counter%+1
goto loop
)
endlocal
pause
実行結果
0
1
2
3
4
続行するには何かキーを押してください . . .
まとめ
遅延環境変数展開をうまく活用することで、より複雑な処理を含むバッチファイルを記述することが可能になります。ただし、遅延環境変数展開が必要なケースと不要なケースの切り分けが難しいので、慣れが必要な機能と感じました。