Windows批处理文件: 什么是变量展开,EnalbeDelayedExpansion是什么意思?

22

"变量扩展"是什么意思?它仅仅指 "变量定义",还是其他的含义?

当我使用 setLocal EnableDelayedExpansion 命令时会发生什么?Google 上的解释不是很清楚。


2
http://ss64.com/nt/delayedexpansion.html ; http://www.robvanderwoude.com/variableexpansion.php - npocmaka
@npocmaka,我读了这些页面。我仍然不明白什么是“变量扩展”,它是否只是意味着“将值放入变量中”? - Aviv Cohn
好的。在这里还要检查一下jeb的答案,链接如下:http://stackoverflow.com/questions/17265882/parse-time-vs-execution-time 和 https://dev59.com/6G855IYBdhLWcg3w5Igb#4095133 - npocmaka
在命令提示符下键入“help setlocal”可以提供文档,使用“setlocal /?”也可以。这有帮助吗?(对我来说读起来很清楚。) - Ken White
2个回答

28
  • 变量扩展是指用变量的值替换括在%!中的变量。
  • %normal%扩展发生在执行一行之前,仅进行一次。这意味着%variable%扩展无论该行被执行多少次(例如在for命令中),都具有相同的值。
  • !delayed!扩展在每次执行该行时都会执行。

请看以下示例:

@echo off
setlocal EnableDelayedExpansion
set "var=Original"
set "var=New" & echo Normal: "%var%", Delayed: "!var!"

输出:

Normal: "Original", Delayed: "New"

另一个:

@echo off
setlocal EnableDelayedExpansion
set "var1=Normal"
set "var2=Delayed"
for /L %%i in (1,1,10) do (
   set "var1=%var1% %%i"
   set "var2=!var2! %%i"
)
echo Normal:  "%var1%"
echo Delayed: "%var2%"

输出:

Normal:  "Normal 10"
Delayed: "Delayed 1 2 3 4 5 6 7 8 9 10"

正常的扩展并不一定是一个劣势,而是取决于它使用的具体情况。例如,在任何其他编程语言中,要交换两个变量的值,你需要第三个变量的帮助,但在批处理中,这可以只用一行代码完成:

set "var1=%var2%" & set "var2=%var1%"

我明白了。让我看看我是否理解:在正常扩展中,任何地方的%var%都会被替换,但它的值是在解析期间确定的。由于每行只解析一次,所以%var%在循环的每次迭代中都是相同的。使用延迟扩展,将%var%替换为其值发生在“运行时”,即实际执行该行时,因此%var%将被其当前正确的值替换。正确吗? - Aviv Cohn
另外,除非是不寻常的情况,我应该总是只使用 !var! 吗? - Aviv Cohn
1
值得澄清的是,在由括号分隔的代码块(例如 if 代码块)的情况下,整个代码块都被视为一行。 (来源) - OfirD
@OfirD 是的,正常扩展发生在顶层命令执行之前,即不是子命令的命令,而延迟扩展发生在叶子命令执行之前,即非复合命令。 - August Karlstrom

9

在批处理中,变量需要用百分号括起来才能展开。

set myVariable=Hello world
echo %myVariable%

这意味着变量扩展。

与其他编程语言相比,批处理并不真正使用变量。
通常只使用它们的扩展。
它的工作方式类似于C/C++的宏扩展。

因此,并不存在用于获取变量长度的字符串长度函数,
但可以编写一个计算文本字符数的函数。

setLocal EnableDelayedExpansion的解释
普通的百分号扩展有两个缺点。

扩展发生在解析行或括在括号中的块时,而不是在执行块时。

让我们看看这个示例。

set var=one

set var=two & echo %var%
echo %var%

输出结果将会是:

one
two

在执行 set var=two 命令之前,echo %var% 将被展开,这可能会在FOR循环中出现问题。
另一个缺点是批处理解析器将解析变量的展开结果。
set var=cat^&dog
echo %var%

var
未知命令“dog”

但百分比扩展自 MS-Dos 的开始就存在了(大约在 1920 年左右)。

DelayedExpansion 添加了一个新的扩展字符,即感叹号!

但是,您必须首先激活它才能使用setlocal EnableDelayedExpansion,这是为了与旧程序兼容。

setlocal EnableDelayedExpansion
set var=one
set var=two & echo !var!
set var=cat^&dog
echo !var!

两只
猫和狗

因此,这解决了百分号扩展的两个问题。

命令行延迟扩展
您不能通过setlocal EnableDelayedExpansion来启用它,在命令行上它没有任何效果。
但是,您可以使用cmd /v:on

set "var=Cat & dog" & cmd /V:on /c echo !var!

在命令行上直接回显!variable!是否可行(而不是在批处理/cmd文件中)? - Rod
@Rod,是的,我已经将这个添加到我的答案中了。 - jeb
@Rod,是的,现在我已经将这个加入到我的答案中了。 - jeb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接