脚本 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 . . .