批处理文件嵌套setlocal - 仅设置一次可选参数

时间:2014-12-19 03:36:31

标签: windows batch-file

我有一个包含一些功能的批处理文件。每个函数都使用setlocal,以便其变量不会污染主批处理脚本。我注意到我只需要在主批处理脚本中第一次使用参数ENABLEDELAYEDEXPANSION而不是每个嵌套的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设置保持不变?

1 个答案:

答案 0 :(得分:6)

嗯,您可以通过编写一些简单的测试来回答您自己的问题。但我会告诉你答案是肯定的,你只需要启用一次延迟扩展。之后每个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的每个新实例化 NOT 都会继承先前会话的延迟扩展状态。通常,每个cmd.exe会话都会启动,并禁用延迟扩展。

这很重要,因为两个管道和FOR /F %%A IN ('someCommand') DO ...都会隐式启动新的cmd.exe会话。有关详细信息,请参阅Why does delayed expansion fail when inside a piped block of code?