批处理:变量间接:通过动态构造的名称获取变量的值

Batch: variable indirection: getting the value of a variable by dynamically constructed name

所以当我运行这个代码时:

@echo off
setlocal enabledelayedexpansion

set lstFolders= First Second 

set intCounter=0
for %%i in (!lstFolders!) do (
    set /a intCounter += 1
    set strFlder=%%i
    set strFolder!intCounter!=!strFlder!
    echo %%i
    echo !strFlder!
    echo !strFolder%intCounter%!
    echo !strFolder1!
    echo !strFolder2!
)

:End
pause
endlocal

结果如下:

First
First
ECHO is off.
First
ECHO is off.
Second
Second
ECHO is off.
First
Second

为什么它不允许我回显使用以下格式创建的变量:!strFolder%intCounter%!?是否有另一种方法来引用此变量并获取其中的数据?

警告:下面的代码仅适用于列表值(%lstFolders% 的标记,例如 First):

  • 不包含空格
  • 也不是以下任何字符。: & | < > "

需要一种不同的循环方法来处理这种情况。

@echo off
setlocal enabledelayedexpansion

set "lstFolders=First Second" 

set intCounter=0
for %%i in (%lstFolders%) do (
      rem Increment the counter
    set /a intCounter += 1
      rem Echo the loop variable
    echo #!intCounter!=%%i
      rem Set variable strFolder<intCounter> to the loop variable's value
    set "strFolder!intCounter!=%%i"
      rem Echo the variable created using variable indirection with for /f ('...')
    for /f "delims=" %%v in ('echo "%%strFolder!intCounter!%%"') do set "thisFolder=%%~v"
    echo %%thisFolder%% ^(via %%strFolder!intCounter!%%^)=!thisFolder!
)

运行 以上结果:

#1=First
%thisFolder% (via %strFolder1%)=First
#2=Second
%thisFolder% (via %strFolder2%)=Second

您要找的是变量间接:

  • 虽然您可以设置一个变量间接(通过一个您从另一个变量的值动态构造的名称 变量),例如,
    • set "strFolder!intCounter!=%%i"!intCounter! 的值为 1,正确设置变量 strFolder1%%i),
  • 不能得到一个变量的值;您需要额外的评估步骤for /f ... ('echo ...') 可以提供。:

    • for /f "delims=" %%v in ('echo "%%strFolder!intCounter!%%"') do ... 解析单引号命令的输出(echo ...)并将结果作为一个整体(delims=)赋值给变量%%v
      %%~v 删除了包含在 echo 参数周围的双引号,以使命令正确处理 shell 元字符,例如 & | < >)。

    • %%strFolder!intCounter!%% 立即计算strFolder!intCounter!strFolder1,如果!intCounter!1,这要归功于封闭的 doubled % 实例,最终成为 literal %strFolder1%,这就是echo 命令通过 for 命令查看它何时为 运行,导致它评估变量引用并扩展为其值。

正如@mklement0 所说,您需要一个额外的评估步骤。
但尽管使用 echo "%%strFolder!intCounter!%%",我还是建议延迟扩展。
由于延迟扩展不受任何内容的影响,echo "%%strFolder... 将因包含引号或感叹号的内容而失败。

@echo off
setlocal enabledelayedexpansion

set "lstFolders=First Second"

set intCounter=0
for %%i in (!lstFolders!) do (
    set /a intCounter+= 1
    set "strFlder=%%i"
    set "strFolder!intCounter!=!strFlder!"
    echo !strFlder!
    set "varname=strFolder!intCounter!"
    for /F "delims=" %%A in (""!varname!"") do echo Indirect %%~A=!%%~A!
)

双引号避免了 FOR/F 循环的 eol 字符问题。