有名な「遅延拡大の罠」に陥ったのはあなたが最初ではありません (そしてあなたが最後ではありません)。
同じブロックで変更した変数を使用する場合は、遅延展開が必要です (ブロックは、括弧内の一連のコマンドです(
および)
)。
遅延変数は!var!
ではなく で参照され%var%
ます。
理由は方法でありcmd
、コードを解析します。完全な行またはブロックが一度に解析され、解析時に通常の変数がその値に置き換えられます。遅延変数は実行時に評価されます。
デモ用の 2 つの簡単なバッチ ファイル:
setlocal EnableDelayedExpansion
set "var=hello"
if 1==1 (
set "var=world"
echo %var% !var!
)
setlocal EnableDelayedExpansion
for /L %%i in (1,1,5) do (
echo %random% !random!
)
注: 行もブロックとして扱われます。
set "var=old"
set "var=new" & echo %var%
遅延拡張あり:
setlocal EnableDelayedExpansion
set "var=old"
set "var=new" & echo !var!
遅延拡張は、コマンド プロンプトでデフォルトでオフになっています。本当に必要な場合は、次のことができます。
cmd /V:ON /C "set "var=hello" & echo !var!"
また、遅延拡張なしで同じことを行う方法もあります (ただしcall
、時間がかかるため遅くなりますが、何らかの理由で遅延拡張を使用できない/使用したくない場合は、別の方法です):
setlocal DISabledelayedexpansion
for /L %%i in (1 1 5) do (
call echo %random% %%random%%
)
どちらの方法も、配列のような変数を表示するために使用できます。
(これは、「別の変数を含む変数」または「ネストされた変数」のようによく聞かれます)
さまざまな状況でそのような配列のような変数を使用するためのコレクションを次に示します。
遅延拡張あり:
setlocal ENableDelayedExpansion
set "num=4"
set "var[%num%]=HELLO"
echo plain delayed: !var[%num%]!
for /L %%i in (4 1 4) do (
echo for delayed: !var[%%i]!
set a=%%i
call echo for delayed with variable: %%var[!a!]%%
)
遅延拡張なし:
setlocal DISableDelayedExpansion
set "num=4"
set "var[%num%]=HELLO"
call echo plain called: %%var[%num%]%%
for /L %%i in (4 1 4) do (
call echo FOR called: %%var[%%i]%%
set a=%%i
call echo FOR called with variable: %%var[%a%]%%
)
注:setlocal
バッチファイル以外では効果がないため、次の場合にdelayedexpansion
のみ機能します。
- バッチファイルで
- 遅延拡張を有効にしてコマンドを開始した場合 (
cmd /V:ON
) (デフォルトでは、コマンドは遅延拡張を無効にして実行されます)
(技術的な背景や高度な技術に興味がある場合は、リンクをたどってください)