Windowsバッチファイルで遅延環境変数展開を使用する
目次
バッチファイルの変数
バッチファイルの変数は、デフォルトでテキスト行が読み取られるときに展開が行われます。
通常は問題にならないのですが、FOR
やIF
で括弧を使用している場合、括弧内部の処理は全体で1行と判定されるため、括弧内でSET
を使用して変数を設定してもうまく設定がされません。
@echo off
setlocal
set A=1
set B=1
if %A% == 1 (
set B=2
echo [IN] A=%A%, B=%B%
)
echo [OUT] A=%A%, B=%B%
pause
[IN] A=1, B=1
[OUT] A=1, B=2
上記コードはif
の内部でB
に2
をセットしていますが、出力結果は1
となっています。
これはif
の処理に入った際に括弧内も含めて変数が展開されるため、%A%
、%B%
ともにif
の前でセットしている1
が展開されるためです。
if 1 == 1 (
set B=2
echo [IN] A=1, B=1
)
このため、if
内のecho
で「[IN] A=1, B=1
」と表示されます。
遅延環境変数展開
上記を回避するためには遅延環境変数展開を使用します。
遅延環境変数展開とは、バッチファイル内で変数がセットされた後、その変数が参照されるまでの間、変数の値が展開されないようにする機能です。
これにより、ループ処理などで変数の値が変わる場合でも、その都度最新の値を取得できます。
遅延環境変数展開を使用するには、バッチファイルの始めにsetlocal enabledelayedexpansion
を記述し、変数名を参照する際は「%変数名%
」ではなく、「!変数名!
」とします。
@echo off
setlocal enabledelayedexpansion
set A=1
set B=1
if !A! == 1 (
set B=2
echo [IN] A=!A!, B=!B!
)
echo [OUT] A=!A!, B=!B!
pause
[IN] A=1, B=2
[OUT] A=1, B=2
上記は遅延環境変数展開を使っているため、括弧内でも変数の値が更新されるようになります。
遅延環境変数を使用しない方法
CALL
コマンドを使用し、新しいバッチファイルのコンテキストを作ることで、遅延環境変数を使わず変数を再評価することも可能です。
CALL
コマンドを使用する場合は変数は「%%変数名%%
」で参照します。
@echo off
setlocal
set A=1
set B=1
if %A% == 1 (
set B=2
call echo [IN] A=%%A%%, B=%%B%%
)
call echo [OUT] A=%%A%%, B=%%B%%
pause
[IN] A=1, B=2
[OUT] A=1, B=2
CALL
コマンドを使用する方法は、遅延環境変数展開と比較してパフォーマンスが劣るため、特別な理由がない限りは遅延環境変数展開を利用する方法が推奨されます。