Ответ 1
Вы не первый, кто попал в знаменитую "ловушку с отложенным расширением" (и вы не будете последним).
Вам нужно отложенное расширение, если вы хотите использовать переменную, которую вы изменили в том же блоке (блок - это серия команд в скобках (
и )
).
Задержанные переменные ссылаются на !var!
вместо %var%
.
Причина в том, что cmd
анализирует код. Полная строка или блок анализируются сразу, заменяя нормальные переменные их значением во время анализа. Задержанные переменные оцениваются во время выполнения.
Два простых пакетных файла для демонстрации:
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
не действует вне пакетных файлов, поэтому отложенное расширение работает только:
- в пакетных файлах
- Когда C была начат с задержкой расширения включено (cmd/V:ON
) (по умолчанию CMD работает с отложенной Дис расширения недееспособной)