楼主的这个例子中 setlocal ENABLEDELAYEDEXPANSION 写在 for 前面就行了,不需要用在循环里
先简单解释下 setlocal 和 endlocal:- setlocal 实现变量本地化的原因是它每次被执行时都会创建一张新的变量表,此后的所有变量操作都在这张新表上进行,上限 32 张表(在 call 中会另行计数),为避免超出这一限制,需要使用 endlocal 来释放由 setlocal 所产生的最新的变量表,表中的变量自然也就随之丢失。
复制代码 再说说为什么许多代码要在循环中用到 setlocal 和 endlocal:
我们在 for 中使用 setlocal 和 endlocal 的目的一般是为了与变量赋值配合,以便在必须使用变量延迟的时候也能输出含有 ! 的字符串,对比下面两个例子:- @echo off&setlocal enabledelayedexpansion
- for /f "delims=" %%a in ("^!tmp^!") do echo !date!-%%a
- ::这里的 !tmp! 在 echo 的时候被解释为变量 tmp 的值,而我们实际上想输出的是 "!tmp!" 这个含有 ! 的字符串本身,可是由于开启了变量扩展后直接引用 %%a,所以其中的 !tmp! 被解释为变量
- pause
复制代码
- @echo off
- for /f "delims=" %%a in ("^!tmp^!") do (
- set str=%%a
- setlocal enabledelayedexpansion
- echo !date!-!str!
- endlocal
- )
- ::经过 set str=%%a 与 setlocal enabledelayedexpansion,!tmp! 被赋值到变量 str,以便在 echo 的时候以 !str! 的形式避开变量延迟对于 %%a 的解释
- pause
复制代码 但是 setlocal 和 endlocal 之间的变量会丢失,解决办法是用 for 将延迟变量 !num! 转换为参数变量 %%a,以便在 endlocal 之后再把 %%a 赋值给 num 变量:- set num=test
- setlocal enabledelayedexpansion
- set num=1234
- rem 如果直接 endlocal,%num% 将还原成 setlocal 之前的最后状态,即 num=test
- endlocal&set num=%num%
- rem 因为 %num% 是在执行 endlocal 之前就被解释的(若是延迟变量 !num!,则只在命令执行前被解释),所以经过再赋值即可保留 num 变量
- echo %num%
复制代码 如果是在复合语句中则没法简单用 endlocal&set num=%num% 解决,此时必须使用变量延迟以保证所得的 num 是即时的,那么应这样:- (set num=test
- setlocal enabledelayedexpansion
- set num=1234
- rem 如果直接 endlocal,%num% 将还原成 setlocal 之前的最后状态,即 num=test
- for %%a in (!num!) do endlocal&set num=%%a
- rem 经过 for 的中转和再赋值,既保证了 !num! 是执行 for 前刚刚被解释的,又保证 endlocal 之后它的值能够得以保留
- )
- echo %num%
复制代码
|