在循环中分配超过 endlocal 的变量

Assign variables past endlocal in a loop

如何在循环中保留 endlocal 之后的多个变量(具有特定前缀)?

变量在循环声明中可见,但在循环体中不可见。

下面是一个使用 echo 而不是变量赋值的示例,以说明变量在 for 主体中不可见。通常,变量赋值将代替 echo:

@echo off

setlocal ENABLEDELAYEDEXPANSION
set TB_1=test1
set TB_2=test2

set TB_ALL_VARS=
for /F "tokens=1 delims==" %%x in ('set TB_') do (
  set TB_ALL_VARS=%%x !TB_ALL_VARS!
)

for %%x in (%TB_ALL_VARS%) do ( echo %%x = !%%x! ) 
echo END LOCAL
endlocal & ( for %%x in (%TB_ALL_VARS%) do ( echo %%x = !%%x! ) )

输出:

TB_2 = test2
TB_1 = test1
END LOCAL
TB_2 = !TB_2!
TB_1 = !TB_1!

可以看到,变量在endlocal之前打印正常,在endlocal之后就打印不出来了。

有没有办法像这样保存过去的endlocal变量?

您正在尝试使用 tunneling ,但是在 endlocal 之后您不能使用 ! 来扩展 variables.Try this:

@echo off

setlocal ENABLEDELAYEDEXPANSION
set TB_1=test1
set TB_2=test2

set TB_ALL_VARS=
for /F "tokens=1 delims==" %%x in ('set TB_') do (
  set TB_ALL_VARS=%%x !TB_ALL_VARS!
)

for %%x in (%TB_ALL_VARS%) do ( echo %%x = !%%x! ) 
echo END LOCAL
endlocal & ( for %%x in (%TB_ALL_VARS%) do ( call echo %%x = %%%%x%% ) )

@echo off

setlocal ENABLEDELAYEDEXPANSION
set TB_1=test1
set TB_2=test2

set TB_ALL_VARS=
for /F "tokens=1 delims==" %%x in ('set TB_') do (
  set TB_ALL_VARS=%%x !TB_ALL_VARS!
)

for %%x in (%TB_ALL_VARS%) do ( echo %%x = !%%x! ) 
echo END LOCAL
endlocal & ( for %%x in (%TB_ALL_VARS%) do (
 setlocal enableDelayedExpansion
 call echo %%x = !%%x! )
 endlocal 
 )

鉴于您的示例代码,我认为您要问的是,"How do I set a dynamic number of variables after endlocal?"您的要求不是很直观,但可能的。将 setendlocal 复合时不能使用延迟扩展。通常可以采用一种变通方法,使用 for 循环到 endlocal & set "var=%%A",这仅在变量和值的数量是静态的情况下才有效。不幸的是,endlocal & forfor... in... do ( endlocal & set ) 的工作方式不同,正如您在自己的测试中无疑发现的那样。

我的解决方案是在 endlocal 之后使用宏进行设置——基本上是将 命令 而不是简单的字符串值放入变量中,然后评估该变量作为一组 set 个命令。

@echo off
setlocal

:: // call ":set" subroutine to do the setting
call :set

:: // display results
set subv

:: // end main runtime
goto :EOF


:: // :set subroutine
:set
setlocal enabledelayedexpansion

:: // any number of variables prefixed by "subv"
set "subv1=1"
set "subv2=2"
set "subv3=3"

:: // init %compound%
set compound=

:: // combine all %subvX% variables into a macro of set var1=val1 & set var2=val2, etc
for /f "delims=" %%I in ('set subv') do set "compound=!compound! & set "%%~I""

:: // evaluate set commands as a macro
endlocal & %compound:~3%
goto :EOF

另一个解决方案是回到我提到的第一个解决方法,格式为 endlocal & set "var=%%A"。通常这只在你知道你只会循环一次时使用,比如

for %%I in ("!var!") do endlocal & set "return=%%~I"

...因为您不想结束本地化太多次。但是您可以通过使用 if not defined 来使用单个 endlocal 进行多值循环:

@echo off
setlocal

call :set
set subv

goto :EOF

:set
setlocal enabledelayedexpansion
set "subv1=1"
set "subv2=2"
set "subv3=3"
set end=
for /f "delims=" %%I in ('set subv') do (
    if not defined end endlocal & set end=1
    set "%%~I"
)
goto :EOF

...并且因为 endlocalset "%%~I" 包含在带括号的代码块中,变量被重新设置并且您的目标实现了。