2014-12-19 2 views
1

У меня есть пакетный файл с некоторыми функциями. Каждая функция использует setlocal так, чтобы ее переменные не загрязняли основной пакетный скрипт. Я заметил, что мне нужен только аргумент ENABLEDELAYEDEXPANSION в основном скрипте партии, а не в каждом вложенном setlocal. Например:Пакетный файл вложенной setlocal - установка необязательных аргументов только один раз

@echo off 
setlocal ENABLEDELAYEDEXPANSION 

set VAR=hi 
CALL :function 

echo bye 
exit /b 0 

:function 
setlocal 
echo !VAR! 
exit /b 0 

Это разрешено в пакетном файле, поскольку я не могу найти его документированным, за исключением случаев, указанных ниже. Это намного проще, чем писать только setlocal для каждой функции, а не указывать дополнительные аргументы.

setlocal /? говорит это о ENABLEDELAYEDEXPANSION:

Эти модификации последнего до команды соответствия Endlocal, независимо от их установки до SETLOCAL команды.

Возможно, это будет означать, что даже с другим setlocal настройки остаются неизменными?

ответ

5

Ну, вы можете ответить на свой вопрос, написав несколько простых тестов. Но я скажу вам, что ответ «да», вам нужно только один раз включить замедленное расширение. Каждый SETLOCAL впоследствии наследует предыдущее состояние с задержкой расширения, если явно не отключено DisableDelayedExpansion.

@echo off 
echo delayed Expansion normally starts out disabled: !temp! 
setlocal enableDelayedExpansion 
echo delayed exapnsion now enabled: !temp! 
call :test 
exit /b 

:test 
setlocal 
echo delayed expansion still enabled: !temp! 
exit /b 

Если вы изучаете партии, то вы должны ожидать, чтобы делать много экспериментов, потому что документация довольно беден, а иногда и просто неправильно.


Ваша стратегия только позволяет замедленное расширение когда-то хорошо, только если вы знаете, что это нормально для того, чтобы быть включен в течение всего сценария.

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

Расширение аргументов CALL %1 или FOR переменных %%A повреждены, если значение содержит ! и включено замедленное расширение. Так много сложных сценариев, которые я пишу, требуют тщательного управления задержанным состоянием расширения.

В рамках одной процедуры вы можете знать состояние в любой момент времени. Но в начале подпрограммы или функции вы можете не знать состояние вызывающего абонента. Как правило, я явно включаю или отключает замедленное расширение в верхней части каждой процедуры, если моя программа требует определенного состояния.


Слово предостережения - Каждая новая конкретизация cmd.exe делает НЕ наследуют состояние отсроченного расширения от предыдущей сессии. Обычно каждый сеанс cmd.exe запускается с отключенным отключением.

Это важно, потому что обе трубы и FOR /F %%A IN ('someCommand') DO ... неявно запускают новые сеансы cmd.exe. См. Why does delayed expansion fail when inside a piped block of code? для получения дополнительной информации.

+0

Спасибо за вашу помощь и слова предостережения! – loop

+0

Есть ли у вас ссылка на то, как замедленное расширение может вызвать проблемы?Я читаю [здесь] (http://stackoverflow.com/a/7896431/894506), он безопасен для специальных символов. – loop

+0

@test - Да, но прочитайте 4-й абзац с конца, а затем попробуйте это в пакетном файле: 'setlocal enableDelayedExpansion & for/f 'delims =" %% A in («Привет, мир! Приятно вас видеть!») do echo %% A'. Он будет печатать только «Hello world». Измените сценарий, чтобы отключить задержанное расширение, и вся фраза с восклицательными знаками будет сохранена. – dbenham

Смежные вопросы