我正在批处理命令中编写脚本,并尝试替换循环内的变量

我正在批处理命令中编写脚本,并尝试替换循环内的变量

脚本 1

echo off
set /a flag = 0
set /a flag = 1
pause

脚本2

echo off
set /a flag = 0
for /l %%x in (1,1,3) do (
    if %flag% == 0 (set /a flag = 1)
    echo %flag%
)
pause

脚本1正在运行,输出是数字1。

脚本2不起作用,输出始终为0。

答案1

传奇的@DavidPostill 说You need to use delayed expansion when using variable inside a loop...不对!。这也许是最容易解释的方法,但这只是解决这个问题的一个方法。早在enabledelayedexpansion使用call :label_name <params>goto :EOF语法之前,我们就已经开始解决这个问题了。我仍然更喜欢这种语法,因为它看起来更像基本时代的gosub和,而不是这种令人厌恶的更改为。return%!

脚本2

:: Think of this part as main().  It quits and exits at the goto :EOF
echo off
set /a flag = 0
for /l %%x in (1,1,3) do call :show_flag "%%x"
pause
goto :EOF

:: -----------------------------------------------------------------------
:: Our function here is not bound by the rules mentioned in other answers.
:: we can change the values of variables in here and they will be handled
:: properly.
:: -----------------------------------------------------------------------
:: function show_flag
:: -----------------------------------------------------------------------
:show_flag
    set incoming_flag_param=%~0
    if [%incoming_flag_param%] == [0] (set /a flag = 1)
    echo %flag%
    goto :EOF

如果您想知道这种语法存在了多久?我相信我是在原始 cmd.exe / NT3.51 中使用过它的。

答案2

脚本2不起作用,输出始终为0。

在循环内使用变量时需要使用延迟扩展。

延迟扩展将导致批处理文件中的变量在执行时而不是在解析时扩展,此选项通过命令打开SETLOCAL EnableDelayedExpansion

  • 变量扩展意味着用其值 C:\WINDOWS 替换变量(例如 %windir%)

  • 默认情况下,在执行每一行之前,扩展只会发生一次。

  • 在这种情况下,“行”包括括号内的表达式,即使它们被格式化为跨越多行。

  • 当打开 !delayed! 扩展时,每次执行该行时或者FOR 循环命令中的每个循环时,变量都会被扩展。

  • 使用循环命令(如FOR、复合或括号表达式), 延迟扩展将允许您始终读取变量的当前值。您可以写入带有或不带有延迟扩展的新变量值。

(重点是我的)

来源:EnableDelayedExpansion - Windows CMD - SS64.com

然后您需要替换%flag%!flag!

@echo off
setlocal enabledelayedexpansion
set /a flag = 0
for /l %%x in (1,1,3) do (
    if %flag% == 0 (set /a flag = 1)
    echo !flag!
)
pause
endlocal

输出:

1
1
1
Press any key to continue . . .

可能更有用:

@echo off
setlocal enabledelayedexpansion
set /a flag = 0
for /l %%x in (1,1,3) do (
    if %flag% == 0 (set /a flag = %%x)
    echo !flag!
)
pause
endlocal

输出:

1
2
3
Press any key to continue . . .

进一步阅读

相关内容