我有一个带有一些功能的批处理文件。每个函数都使用 setlocal
以便其变量不会污染主批处理脚本。我注意到我第一次只需要在主批处理脚本中而不是在每个嵌套的 setlocal 中使用参数 ENABLEDELAYEDEXPANSION
。例如:
@echo off
setlocal ENABLEDELAYEDEXPANSION
set VAR=hi
CALL :function
echo bye
exit /b 0
:function
setlocal
echo !VAR!
exit /b 0
这在批处理文件中是否允许,因为我找不到它的记录,除非如下所述。这当然比只为每个函数编写
setlocal
而不是指定附加参数要容易得多。setlocal /?
关于 ENABLEDELAYEDEXPANSION 是这样说的:所以也许这意味着即使使用另一个 setlocal 设置保持不变?
最佳答案
好吧,您可以通过编写一些简单的测试来回答您自己的问题。但是我会告诉你答案是肯定的,你只需要启用一次延迟扩展。之后的每个 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
如果您正在学习批处理,那么您应该期望进行大量实验,因为文档非常糟糕,有时甚至是错误的。
只有当您知道可以在整个脚本中启用延迟扩展时,您只启用一次延迟扩展的策略才是好的。
诚然,延迟扩展在批处理中解决了很多讨厌的问题,但不幸的是它也可能导致问题。
如果值包含
%1
并且启用了延迟扩展,则 CALL 参数 %%A
或 FOR 变量 !
的扩展会损坏。我编写的许多中等复杂的脚本需要仔细管理延迟扩展状态。在单个例程中,您可以了解任何给定时间的状态。但是在子程序或函数开始时,您可能不知道调用者的状态。作为一般规则,如果我的例程需要特定状态,我会在每个例程的顶部明确启用或禁用延迟扩展。
警告 - cmd.exe 的每个新实例都不会 而不是 从前一个 session 继承延迟扩展状态。通常,每个 cmd.exe session 都在禁用延迟扩展的情况下开始。
这很重要,因为管道和
FOR /F %%A IN ('someCommand') DO ...
都会隐式启动新的 cmd.exe session 。有关更多信息,请参阅 Why does delayed expansion fail when inside a piped block of code?。关于windows - 批处理文件嵌套 setlocal - 仅设置一次可选参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27559347/