如果您处于循环或任何带括号的代码块中,则无法使用该ENDLOCAL & set BAT2_VAR=%BAT2_VAR%
方法。
这样的事情会失败
REM delayed expansion is disabled to start
for ... %%A in (....) do (
REM must SET before enabling delayed expansion to preserve ! in %%A value
set var=%%A
REM the remainder of the loop needs delayed expansion
setlocal enableDelayedExpansion
REM do something with !var!
call batch2 !var!
REM maybe the batch2 modifies var some more
REM Must endlocal and preserve the value. The attempt below fails because %var% will
REM be the value that existed before the loop was entered
endlocal & set "var=%var%"
)
一个简单的解决方法是通过 FOR 变量传输值
REM delayed expansion is disabled to start
for ... %%A in (....) do (
REM must SET before enabling delayed expansion to preserve ! in %%A value
set var=%%A
REM the remainder of the loop needs delayed expansion
setlocal enableDelayedExpansion
REM do something with !var!
call batch2 !var!
REM maybe the batch2 modifies var some more
REM the code below successfully transports the value across the endlocal barrier
for /f "delims=" %%B in ("!var!") do endlocal & set "var=%%B"
)
您说您的批次可能会设置许多您需要保留的值。通常,您将返回变量的名称传递给您的 CALLed 例程,然后您的例程可以执行以下操作:
set "%~2=return value1"
set "%~3=return value2"
... etc.
您会知道所有变量的名称,但这可能需要大量代码才能将所有值传输到 endlocal 屏障。
您可以使用公共前缀为所有变量添加前缀,然后使用 FOR /F 循环来保留这些值。FOR /F ('command') 的整个结果集在任何迭代开始之前被缓存。
您的 CALLed 批处理可以设置变量prefix.var1
, prefix.var2
, ... prefix.varN
,并且以下代码将起作用
REM delayed expansion is disabled to start
for ... %%A in (....) do (
REM must SET before enabling delayed expansion to preserve ! in %%A value
set var=%%A
REM the remainder of the loop needs delayed expansion
setlocal enableDelayedExpansion
REM do something with !var!
call batch2 !var! prefix.
REM the batch2 set variables prefixed by prefix.
REM Must endlocal and preserve all values.
for /f "delims=" %%B in ('set prefix.') do (
if "!"=="" endlocal
set "%%B"
)
)
该if "!"=="" endlocal
行是仅在第一次内循环迭代时才使用 endlocal 的绝妙技巧。它依赖于延迟扩展在外循环之前被禁用的事实,并在每次外循环迭代的顶部附近启用。