Windows批处理编程:间接/嵌套变量评估

Sys*_*Lol 5 windows command-line batch-file

我们有一个列出一堆路径的文本文件,以及一个从该文件中读取行的批处理文件.

例如,TargetFolders.txt可能包含以下行:

%ProgramFiles%\Acme\FooBar %VersionNumber%
Run Code Online (Sandbox Code Playgroud)

当然,当我们从文本文件中读取这一行时(使用FOR命令),变量%% I接收实际行文本,使用%符号而不是替换变量值.所以,

SET VersionNumber=7.0
FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO (
    echo Folder: %%I
)
Run Code Online (Sandbox Code Playgroud)

打印

Folder: %ProgramFiles%\Acme\FooBar %VersionNumber%
Run Code Online (Sandbox Code Playgroud)

如何使它替换实际的变量值,以便打印

Folder: C:\Program Files\Acme\FooBar 7.0
Run Code Online (Sandbox Code Playgroud)

Irf*_*rfy 8

SET VersionNumber=7.0
FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO (
    for /F "usebackq delims=" %%J in (`echo %%I`) do echo Folder: %%J
)
Run Code Online (Sandbox Code Playgroud)

你去吧 (这就是你想要的,对吧?)

  • OT:我认为我们在这里默认同意NT shell编程本身就是一个恐怖,与linux/unix shell相比...... (3认同)

dbe*_*ham 6

只需添加CALL即可解决您的问题.(也是你对VersionNumber的定义错了)

SET VersionNumber=7.0
FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO (
  call echo Folder: %%I
)
Run Code Online (Sandbox Code Playgroud)

但是,这将失败,如果你的文件包含未加引号的特殊字符,如&,>,<,|.

例如,以下行将失败:

%ProgramFiles%\This&That\ %VersionNumber%
Run Code Online (Sandbox Code Playgroud)

如果被引用它将起作用

"%ProgramFiles%\This&That\" %VersionNumber%
Run Code Online (Sandbox Code Playgroud)

CALL也将破坏任何引用的插入符号:"^"将成为"^^"

最好的解决方案是修改文本文件并将其替换%!.

!ProgramFiles!\Acme\FooBar !VersionNumber!
!ProgramFiles!\This&That !VersionNumber!
Run Code Online (Sandbox Code Playgroud)

现在,您可以安全地使用延迟扩展来扩展循环中的变量.

setlocal enableDelayedExpansion
SET VersionNumber=7.0
FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO (
  echo Folder: %%I
)
Run Code Online (Sandbox Code Playgroud)

如果您的文本文件已经存在!,那么必须对其进行转义.^如果它出现在带有a的行上,也必须进行转义!.

preserve caret ^^ and exclamation ^! by escaping
caret ^ without exclamation is no problem
Run Code Online (Sandbox Code Playgroud)

或者,您可以将变量替换为插入符号和感叹号文字

alternate method to preserve caret !c! and exclamation !x!
caret ^ without exclamation still no problem
Run Code Online (Sandbox Code Playgroud)

然后在批处理中定义变量

setlocal enableDelayedExpansion
set "x=^!"
set "c=^"
SET VersionNumber=7.0
FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO (
  echo Folder: %%I
)
Run Code Online (Sandbox Code Playgroud)