Подтвердить что ты не робот

Как работают SETLOCAL и ENABLEDELAYEDEXPANSION?

В большинстве скриптов я замечаю, что они обычно находятся в одной строке:

SETLOCAL ENABLEDELAYEDEXPANSION

Являются ли эти две отдельные команды и могут быть записаны на отдельных строках?

Будет ли установка ENABLEDELAYEDEXPANSION отрицательно влиять на script, если она установлена ​​в первых строках script и не отключена до конца script?

4b9b3361

Ответ 1

ENABLEDELAYEDEXPANSION - это параметр, переданный команде SETLOCAL (смотрите setlocal /?)

Его эффект живет на время script или ENDLOCAL:

Когда достигнут конец пакета script, подразумевается ENDLOCALвыполняется для любых выдающихся команд SETLOCAL, выпущенных этой группой script.

В частности, это означает, что если вы используете SETLOCAL ENABLEDELAYEDEXPANSION в script, любые изменения переменных среды теряются в конце, если вы не принять специальные меры.

Ответ 2

Я думаю, вы должны понять, что такое замедленное расширение. Существующие ответы не объясняют это (достаточно) ИМХО.

Ввод SET /? достаточно хорошо объясняет:

Отложенное расширение переменной среды полезно для того, чтобы обойти ограничения текущего расширения, которое происходит, когда линия текст читается, а не когда он выполняется. Следующий пример демонстрирует проблему с немедленным расширением переменной:

set VAR=before
if "%VAR%" == "before" (
    set VAR=after
    if "%VAR%" == "after" @echo If you see this, it worked
)

никогда не будет отображать сообщение, так как% VAR% в BOTH IF заявлениях заменяется, когда считывается первый оператор IF, поскольку он логически включает тело IF, которое является составной формулировкой. Таким образом, IF внутри составного утверждения действительно сравнивается "до" с "после", которое никогда не будет равным. Аналогично, следующий пример не будет работать должным образом:

set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%

в том, что он не будет создавать список файлов в текущем каталоге, но вместо этого просто установите для переменной LIST последний найденный файл. Опять же, это потому, что% LIST% расширяется только один раз, когда FOR инструкция читается, и в это время переменная LIST пуста. Итак фактический цикл FOR, который мы выполняем:

for %i in (*) do set LIST= %i

который просто устанавливает параметр LIST в найденный последний файл.

Отложенное расширение переменной среды позволяет использовать character (восклицательный знак) для расширения переменных среды при время исполнения. Если включено замедленное расширение переменной, вышеуказанное примеры могут быть записаны следующим образом для работы в соответствии с назначением:

set VAR=before
if "%VAR%" == "before" (
    set VAR=after
    if "!VAR!" == "after" @echo If you see this, it worked
)

set LIST=
for %i in (*) do set LIST=!LIST! %i
echo %LIST%

Другим примером является этот командный файл:

@echo off
setlocal enabledelayedexpansion
set b=z1
for %%a in (x1 y1) do (
 set b=%%a
 echo !b:1=2!
)

Это печатает x2 и y2: каждый 1 заменяется на 2.

Без setlocal enabledelayedexpansion восклицательные знаки таковы, поэтому он будет дважды повторяться !b:1=2!.

Поскольку обычные переменные среды расширяются при чтении инструкции (блока), расширение %b:1=2% использует значение b перед циклом: z2 (но y2, если не задано).

Ответ 3

Часть ENABLEDELAYEDEXPANSION НЕОБХОДИМА в некоторых программах, использующих задержанное расширение, то есть которое принимает значение переменных, которые были изменены внутри команд IF или FOR, путем включения их имен в восклицательные знаки.

Если вы включите это расширение в script, которое его не требует, script ведет себя иначе, только если оно содержит имена, заключенные в восклицательные знаки! LIKE!!ЭТИ!. Обычно имя просто стирается, но если переменная с тем же именем существует случайно, то результат непредсказуем и зависит от значения такой переменной и места ее появления.

Часть SETLOCAL НЕОБХОДИМА только в нескольких специализированных (рекурсивных) программах, но обычно используется, когда вы хотите, чтобы вы не изменяли какую-либо существующую переменную с тем же именем случайно или если вы хотите автоматически удалить все переменные используемые в вашей программе. Однако, поскольку для включения замедленного расширения нет отдельной команды, требующие этого программы также должны включать часть SETLOCAL.

Ответ 4

Реальная проблема часто существует, потому что любые переменные, установленные внутри, не будут экспортироваться при завершении этого командного файла. Поэтому его невозможно экспортировать, что вызвало у нас проблемы. В результате я просто установил реестр, чтобы ВСЕГДА использовал задержанное расширение (я не знаю, почему это не значение по умолчанию, может быть проблемой скорости или устаревшей совместимости.)