可变替代

与其他编程语言不同,在批处理文件中,在运行批处理脚本之前,变量将由其实际值替换。换句话说,当命令处理器将脚本入内存时,而不是稍后运行脚本时,将进行替换。

这使得变量可以作为脚本中的命令使用,也可以作为脚本中其他变量名称的一部分使用。此上下文中的脚本是代码的行或块,用圆括号括起来:()

但是这种行为确实意味着你无法在块内更改变量的值!

SET VAR=Hello
FOR /L %%a in (1,1,2) do (
    ECHO %VAR%
    SET VAR=Goodbye
)

将打印

Hello
Hello

因为(如你所见,在观察命令窗口中运行的脚本时),它被评估为:

SET VAR=Hello
FOR /L %%a in (1,1,2) do (
    echo Hello
    SET VAR=Goodbye
)

在上面的示例中,当脚本被读入内存时,ECHO 命令被评估为 Hello,因此脚本将永远回显 Hello,但是通过脚本进行了多次传递。

实现更传统变量行为(在脚本运行时扩展变量)的方法是启用延迟扩展。这涉及在循环指令之前将该命令添加到脚本中(通常是 FOR 循环,在批处理脚本中),并在变量名称中使用感叹号(!)而不是百分号(%):

setlocal enabledelayedexpansion 
SET VAR=Hello
FOR /L %%a in (1,1,2) do (
    echo !VAR!
    SET VAR=Goodbye
)
endlocal

将打印

Hello
Goodbye

语法%%a in (1,1,2) 使循环运行 2 次:第一次,变量承载其初始值’Hello’,但是在第二次循环中循环 - 执行第二个 SET 指令作为第一次传递的最后一个动作 - 这已经改为修改后的值’Goodbye’。

高级变量替换

现在,一种先进的技术。使用 CALL 命令允许批处理命令处理器扩展位于脚本同一行的变量。通过重复使用 CALL 和修饰符,可以实现多级扩展。

这在例如 FOR 循环中很有用。如下例所示,我们有一个编号的变量列表:

"c:\MyFiles\test1.txt" "c:\MyFiles\test2.txt" "c:\MyFiles\test3.txt"

我们可以使用以下 FOR 循环实现此目的:

setlocal enabledelayedexpansion
for %%x in (%*) do (
    set /a "i+=1"
    call set path!i!=%%~!i!
    call echo %%path!i!%%
)
endlocal

输出:

c:\MyFiles\test1.txt
c:\MyFiles\test2.txt
c:\MyFiles\test3.txt

请注意,变量 !i! 首先扩展到其初始值 1,然后生成的变量%1 扩展到其实际值 c:\MyFiles\test1.txt。这是变量 i双重扩展。在下一行,i 再次双重展开,使用 CALL ECHO 命令和%%变量前缀,然后打印到屏幕上(即显示在屏幕上)。

在每次连续通过循环时,初始数量增加 1(由于代码 i+=1)。因此,它在第二次通过环路时增加到 2,在第三次通过时增加到 3。因此,每次通过时,回显到屏幕的字符串都会改变。