Назад | Перейти на главную страницу

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

Ожидаемый ввод: Начало = 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

Не уверен, почему first присваивается значение 401, оцените любую помощь

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