Для цикла в командном файле
Ожидаемый ввод: начало =1, конец =500, интервал =100
Ожидаемый результат:
1, 100
101, 200
201, 300
301, 400
401, 500
@echo off
set start=1
set end=500
set interval=100
for /L %%g in (%start%, %interval%, %end%) do (
set first=%%g
set /a last=%first% -1 + %interval%
echo %first% , %last%
)
Фактический вывод:
401, 401 -1 + 100
401, 401 -1 + 100
401, 401 -1 + 100
401, 401 -1 + 100
401, 401 -1 + 100
Не уверен, почему сначала присваивается значение 401, оцените любую помощь
2 ответа
Это классическая проблема с отложенным расширением. Тип help set
или же set /?
из командной строки для обсуждения отложенного расширения (чуть позже половины полной справки).
Нормальное расширение с использованием %var%
происходит при разборе строки. Проблема в том, что весь блок цикла FOR анализируется за один проход. Итак, вы видите постоянное значение, которое существовало до начала цикла. Значение 401 вероятно осталось от предыдущего запуска.
Решением является задержка расширения. Сначала вы должны включить его, используя setlocal enableDelayedExpansion
, Тогда вы используете !var!
вместо %var%
, Это даст значение во время выполнения, а не во время разбора.
Также нет необходимости расширять числовые переменные при использовании set /a
,
@echo off
setlocal enableDelayedExpansion
set start=1
set end=500
set interval=100
for /L %%g in (%start%, %interval%, %end%) do (
set /a first=%%g, last=first-1+interval
echo !first!, !last!
)
@dbenham прямо сейчас. Я выброшу альтернативу. Я нахожу задержанное расширение немного уродливым и сбивающим с толку для более длинных подпрограмм, поэтому я буду иметь тенденцию быть одиноким call
как "тело" for
петля. Внутри call
расширение переменной происходит "нормально". Заметим:
@echo off
setlocal
set start=1
set end=500
set interval=100
for /L %%g in (%start%, %interval%, %end%) do call :_d %%g
endlocal
goto :EOF
:_d
set /a last=%1 - 1 + interval
echo %1, %last%
Для этого конкретного случая это, конечно, больше кода, но для менее тривиальных пакетных файлов я думаю, что это "победа".
Как в сторону: у вас нет setlocal
/ endlocal
там, поэтому значения для first
а также last
будет сохраняться при выполнении, при условии, что вы продолжаете запускать их в одной и той же оболочке, и давать вам разные результаты при втором запуске кода. Я склонен оборачивать свои командные файлы в setlocal
/ endlocal
пару для предотвращения "утечки" переменных, которые я использую в скрипте, в среду родительской оболочки.
Наконец, я повторю то, что говорит @VasiliSyrakis: если вы можете избежать использования cmd.exe
тогда, во что бы то ни стало, избегайте этого. Я склонен писать много вещей в пакетном режиме, но, по общему признанию, это немного похоже на забивание гвоздей отверткой для многих проблем.