Windows 批处理编程:间接/嵌套变量评估
我们有一个列出一堆路径的文本文件,以及一个从该文件读取行的批处理文件。
例如,TargetFolders.txt 可能包含以下行:
%ProgramFiles%\Acme\FooBar %VersionNumber%
当然,当我们从文本文件中读取此行(使用 FOR 命令)时,变量 %%I 会接收实际的行文本,并带有 % 符号,而不是替换变量值。那么,
SET VersionNumber=7.0
FOR /F "eol=; delims=" %%I IN (TargetFolders.txt) DO (
echo Folder: %%I
)
打印
Folder: %ProgramFiles%\Acme\FooBar %VersionNumber%
如何让它替换实际的变量值,以便打印
Folder: C:\Program Files\Acme\FooBar 7.0
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
就这样吧。 (这就是你想要的,对吧?)
There you go. (This is what you wanted, right?)
只需添加 CALL 即可解决您的问题。 (而且您对 VersionNumber 的定义也是错误的)
但是,如果您的文件包含未加引号的特殊字符,例如
&
、>
、<
,则此操作将会失败,<代码>|。例如,以下行将失败:
如果它被引用,它将起作用
CALL 还将破坏任何带引号的插入符号:
"^"
将变为"^^"
最好解决方案是修改您的文本文件并将每个
%
替换为!
。现在您可以安全地使用延迟扩展来扩展循环内的变量。
如果您的文本文件已经包含要保留的
!
,则必须对其进行转义。另外,如果^
出现在带有!
的行上,则必须对其进行转义。或者,您可以用变量替换脱字符号和感叹号文字
,然后在批处理中定义变量
Simply adding a CALL may solve your problem. (also your definition of VersionNumber was wrong)
But this will fail if your file contains unquoted special characters like
&
,>
,<
,|
.For example, the following line would fail:
It will work if it is quoted
The CALL will also mangle any quoted carets:
"^"
will become"^^"
The best solution would be to modify your text file and replace each
%
with!
.Now you can safely use delayed expansion to expand the variables within the loop.
If your text file already has
!
that you want to preserve, then it must be escaped. Also^
will have to be escaped if it appears on a line with a!
.Alternatively you can substitute variables for caret and exclamation literals
And then define the variables in your batch
为了用更强大的变体补充现有的有用答案,该变体还正确处理以下嵌入字符:
& | < > ^
[1]:
请注意,为了简单起见,我使用字符串来驱动外部循环,其文字值 - 稍后将通过内部循环 - 是
%ProgramFiles%\Acme\FooBar %VersionNumber%
,因为%
实例加倍。这会产生类似于
Folder 的内容: [C:\程序Files\Acme\FooBar 0.7]
注意:
for /f
解释一个单引号字符串('...') 作为要执行的命令并捕获其输出;
delims=
告诉for
将输出作为一个整体捕获到单个变量中。(虽然您可以将
usebackq
与`...`
封闭的命令一起使用,但在这种情况下这样做没有任何优势。)请注意对外部循环变量的引用是如何用双引号引起来的(
"%%f"
),这使得值可以包含所述特殊字符而无需破坏echo
命令。因为输出也将被双引号括起来,所以
~
运算符用于在回显时从捕获的值中去除封闭的双引号(%%~g
)。[1] 另外处理嵌入式
"
实例的解决方案比较棘手:这会产生:
"[Windows_NT & %ba^r | (baz)""]"
To complement the existing helpful answers with a more robust variant that also handles the following embedded characters correctly:
& | < > ^
[1]:
Note that for simplicity I'm using a string to drive the outer loop, whose literal value - to be expanded later by the inner loop - is
%ProgramFiles%\Acme\FooBar %VersionNumber%
, due to the doubled%
instances.This yields something like
Folder: [C:\Program Files\Acme\FooBar 0.7]
Note:
for /f
interprets a single-quoted string ('...'
) as a command to execute and whose output to capture;delims=
tellsfor
to capture the output as a whole in a single variable.(While you can use
usebackq
with a`...`
-enclosed command instead, there's no advantage to doing so in this case.)Note how the reference to the outer loop's variable is double-quoted (
"%%f"
), which is what allows the value to contain said special characters without breaking theecho
command.Because the output will then also be double-quoted, the
~
operator is used to strip the enclosing double quotes from the captured value on echoing it (%%~g
).[1] A solution that additionally handles embedded
"
instances is trickier:This yields:
"[Windows_NT & %ba^r | (baz) <mo'>""]"