Windows 批处理(BAT文件)循环中变量的值不变问题
问题:
在Windows批处理中,试图在循环中打印一个计算变量,但结果却是该变量的值总是不变:
@echo off
title timeout 函数测试
@echo 定时开始 ......
set k =0
for /L %%i in (1,1,10) do (
timeout /T 5 > nul
@echo %%i
set /a k = %%i * 5
echo %k% 秒过去了
)
@echo 定时结束。
上面这段代码的含义是,定时5秒循环10次,每次定时结束,打印“多少秒过去了”。但结果却是这样的:
D:\test\BAT>timeout-test.bat
定时开始 ......
1
50 秒过去了
2
50 秒过去了
3
50 秒过去了
4
50 秒过去了
5
50 秒过去了
6
50 秒过去了
7
50 秒过去了
8
50 秒过去了
9
50 秒过去了
10
50 秒过去了
定时结束。
可见,变量k的值并没有随着循环变量i的值变化而变化。
解决:
该问题和Windows批处理脚本的处理模式有关,我的理解是:批处理是读一行解释、执行一行,解释完后(变量的替换等),就不再解释了,就是说即便外部程序在逻辑上又改变了变量的值,但解释器已经不再理会了。
解决方法就是使用延迟变量解释,告诉解释器这是一个变量,后面的值还会改变。
使用延迟变量条件:
(1)打开延迟扩展设置: setlocal enabledelayedexpansion
(2)使用!k!(2个感叹号夹1个变量)来读取变量,不开启延迟扩展时,读取方式是 %k%(2个百分号夹1个变量)
改进后的代码:
@echo off
setlocal enabledelayedexpansion
title timeout 函数测试
@echo 定时开始 ......
set k =0
for /L %%i in (1,1,10) do (
timeout /T 5 > nul
@echo %%i
set /a k = %%i * 5
@echo !k! 秒过去了
)
@echo 定时结束。
改进后的效果:
D:\test\BAT>timeout-test.bat
定时开始 ......
1
5 秒过去了
2
10 秒过去了
3
15 秒过去了
4
20 秒过去了
5
25 秒过去了
6
30 秒过去了
7
35 秒过去了
8
40 秒过去了
9
45 秒过去了
10
50 秒过去了
定时结束。
可见,改进后的程序能够按照预期目标完整地输出定时信息。
说明:
1、批处理中,数学计算表达式的写法:set /a [表达式]
2、不显示命令行本身: @命令行
参考:
1、批处理中setlocal enabledelayedexpansion的作用详细整理,https://www.jb51.net/article/29323.htm