标题: [其他] [已解决]批处理SetLocal 的一些疑问与讨论 [打印本页]
作者: greenworld 时间: 2010-12-28 10:45 标题: [已解决]批处理SetLocal 的一些疑问与讨论
最近写了些代码,有时需开启变量延迟,但为了避免处理有!号路径或文件时出错,又不能全开,只能选择性的开了又关,关了再开...于是就发现了SetLocal的一些问题...这里讨论一下- @echo off
- set a=ABC
- SetLocal EnableDelayedExpansion
- set a=IJK
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
复制代码
结果为 IJK- @echo off
- set a=ABC
- SetLocal EnableDelayedExpansion
- set a=IJK
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
- SetLocal EnableDelayedExpansion
- set a=OPQ
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
复制代码
结果是 OPQ
但是,- @echo off
- set a=ABC
- SetLocal EnableDelayedExpansion
- set a=IJK
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
- call :A
- echo %a%
- pause
- goto :eof
- :A
- SetLocal EnableDelayedExpansion
- set a=OPQ
- SetLocal DisableDelayedExpansion
复制代码
结果是 IJK
而- @echo off
- set a=ABC
- SetLocal EnableDelayedExpansion
- set a=IJK
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
- call :A
- echo %a%
- pause
- goto :eof
- :A
- ::SetLocal EnableDelayedExpansion
- set a=OPQ
- ::SetLocal DisableDelayedExpansion
复制代码
结果却是 OPQ
而下面- @echo off
- set a=ABC
- SetLocal EnableDelayedExpansion
- set a=IJK
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
- goto :A
- :A
- SetLocal EnableDelayedExpansion
- set a=OPQ
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
复制代码
结果还是 OPQ
所以大概的结论是,call 会让 SetLocal EnableDelayedExpansion 开辟新的变量空间,此时对环境变量来说,相当于SetLocal...而SetLocal DisableDelayedExpansion则相当于endlocal
作者: hanyeguxing 时间: 2010-12-28 12:00
原帖由 greenworld 于 2010-12-28 10:45 发表
所以大概的结论是,call 会让 SetLocal EnableDelayedExpansion 开辟新的变量空间,此时对环境变量来说,相当于SetLocal...而SetLocal DisableDelayedExpansion则相当于endlocal
和 enabledelayedexpansion 、 disabledelayedexpansion 参数没有关系。
1,不要频繁使用setlocal,如果不及时Endlocal会造成超过最大允许递归层(xp下是32)
2,每次setlocal本地化时就开启了一个新的(子层)变量空间,并且保存新的变量变化,命令对变量的读写也在当前层(可从父层继承)。
而call返回后对变量的读写则回到了原来(父层)的变量空间。
最大递归层测试:- @echo off
- for /l %%a in (1,1,33) do setlocal&echo 第 %%a 层
- pause
复制代码
各层之间的继承关系演示:- @echo off
- set/a a=1,b=1,c=1
- echo 0:%a%,%b%,%c%
- call:a
- echo 0_:%a%,%b%,%c%
- pause&exit
- :a
- setlocal
- set a=2
- echo a:%a%,%b%,%c%
- call:b
- echo a_:%a%,%b%,%c%
- goto:eof
- :b
- setlocal
- set b=2
- echo b:%a%,%b%,%c%
- call:c
- echo b_:%a%,%b%,%c%
- goto:eof
- :c
- setlocal
- set c=2
- echo c:%a%,%b%,%c%
复制代码
[ 本帖最后由 hanyeguxing 于 2010-12-28 19:54 编辑 ]
作者: Batcher 时间: 2010-12-28 13:53
参考:批处理最大限度原样输出含特殊字符的指定行内容
http://bbs.bathome.net/thread-4580-1-1.html
作者: tmplinshi 时间: 2010-12-28 14:03
经测试,只要在子过程使用了 SetLocal 命令(以下任意一句)
SetLocal
SetLocal EnableDelayedExpansion
SetLocal EnableExtensions
子过程中设置的值就不会返回。
为什么会这样呢?
在“SetLocal /?”的帮助中说到,如果在批处理中使用了 SetLocal 命令,那么在批处理结尾会有一个隐含的 ENDLOCAL 被执行。
所以原因应该就是,子过程也被当做是一个批处理的结束,所以当子过程中执行了 SetLocal,子过程结尾处就会执行 EndLocal。
[ 本帖最后由 tmplinshi 于 2010-12-28 14:38 编辑 ]
作者: hanyeguxing 时间: 2010-12-28 14:32
- @echo off&setlocal enableDelayedExpansion
- for /l %%a in (1,1,8100) do set a=!a!0
- echo 完成初始化
- for /l %%a in (1,1,90000) do call:a %%a
- echo 完成测试
- pause&exit
- :a
- setlocal
- echo %1
- set #%1=%a%
复制代码
中间没有报任何错,显然子过程结束时执行了 EndLocal 。
[ 本帖最后由 hanyeguxing 于 2010-12-28 14:35 编辑 ]
作者: zqz0012005 时间: 2010-12-28 22:06
你们两个还在讨论这个问题?
对Windows系统自带的手册(主要指Help目录下的东西,还包括虽不直接提供但微软网站可下载且很常用的,如script56.chm)一定要滚瓜烂熟,奸里面的确有很多好东西。
装操作系统一定要尽可能安装原版!集成补丁的也行,但不要装对系统改动太大的,更不要装精简版。
作者: ddddxxxxx 时间: 2011-7-27 16:52
- @echo off
- set a=ABC
- SetLocal EnableDelayedExpansion
- set a=IJK
- SetLocal DisableDelayedExpansion
- echo %a%
- pause
- call :A
- echo %a%
- pause
- goto :eof
- :A
- ::SetLocal EnableDelayedExpansion
- set a=OPQ
- ::SetLocal DisableDelayedExpansion
复制代码
我刚刚接触批处理不久?能帮我解释一下“::SetLocal EnableDelayedExpansion”这里的冒号什么意思吗?为什么运行结果会和上面一个代码不同,这双冒号起了什么作用?
作者: tmplinshi 时间: 2011-7-27 17:02
本帖最后由 tmplinshi 于 2011-7-27 17:14 编辑
回复 7# ddddxxxxx
双冒号是无效的标签。因为是标签,所以双冒号后面的是标签名;因为是无效标签,所以不会影响正常标签。总之,双冒号是用来注释的。
作者: ddddxxxxx 时间: 2011-7-27 18:50
回复 8# tmplinshi
谢谢斑竹解释。我又看了相关的东西 ,大致懂了。
作者: taofan712 时间: 2017-3-2 00:18
原来如此,之前阅读一些代码总是看不懂,原来setlocal意义在这里,受教了。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |