Для цикла в командном файле

Ожидаемый ввод: начало =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 тогда, во что бы то ни стало, избегайте этого. Я склонен писать много вещей в пакетном режиме, но, по общему признанию, это немного похоже на забивание гвоздей отверткой для многих проблем.

Другие вопросы по тегам