[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[其他] [已解决]批处理SetLocal 的一些疑问与讨论

最近写了些代码,有时需开启变量延迟,但为了避免处理有!号路径或文件时出错,又不能全开,只能选择性的开了又关,关了再开...于是就发现了SetLocal的一些问题...这里讨论一下
  1. @echo off
  2. set a=ABC
  3. SetLocal EnableDelayedExpansion
  4. set a=IJK
  5. SetLocal DisableDelayedExpansion
  6. echo %a%
  7. pause
复制代码
结果为 IJK
  1. @echo off
  2. set a=ABC
  3. SetLocal EnableDelayedExpansion
  4. set a=IJK
  5. SetLocal DisableDelayedExpansion
  6. echo %a%
  7. pause
  8. SetLocal EnableDelayedExpansion
  9. set a=OPQ
  10. SetLocal DisableDelayedExpansion
  11. echo %a%
  12. pause
复制代码
结果是 OPQ

但是,
  1. @echo off
  2. set a=ABC
  3. SetLocal EnableDelayedExpansion
  4. set a=IJK
  5. SetLocal DisableDelayedExpansion
  6. echo %a%
  7. pause
  8. call :A
  9. echo %a%
  10. pause
  11. goto :eof
  12. :A
  13. SetLocal EnableDelayedExpansion
  14. set a=OPQ
  15. SetLocal DisableDelayedExpansion
复制代码
结果是 IJK

  1. @echo off
  2. set a=ABC
  3. SetLocal EnableDelayedExpansion
  4. set a=IJK
  5. SetLocal DisableDelayedExpansion
  6. echo %a%
  7. pause
  8. call :A
  9. echo %a%
  10. pause
  11. goto :eof
  12. :A
  13. ::SetLocal EnableDelayedExpansion
  14. set a=OPQ
  15. ::SetLocal DisableDelayedExpansion
复制代码
结果却是 OPQ

而下面
  1. @echo off
  2. set a=ABC
  3. SetLocal EnableDelayedExpansion
  4. set a=IJK
  5. SetLocal DisableDelayedExpansion
  6. echo %a%
  7. pause
  8. goto :A
  9. :A
  10. SetLocal EnableDelayedExpansion
  11. set a=OPQ
  12. SetLocal DisableDelayedExpansion
  13. echo %a%
  14. pause
复制代码
结果还是 OPQ

所以大概的结论是,call 会让 SetLocal EnableDelayedExpansion 开辟新的变量空间,此时对环境变量来说,相当于SetLocal...而SetLocal DisableDelayedExpansion则相当于endlocal
1

评分人数

原帖由 greenworld 于 2010-12-28 10:45 发表
所以大概的结论是,call 会让 SetLocal EnableDelayedExpansion 开辟新的变量空间,此时对环境变量来说,相当于SetLocal...而SetLocal DisableDelayedExpansion则相当于endlocal

enabledelayedexpansion  、 disabledelayedexpansion 参数没有关系。
1,不要频繁使用setlocal,如果不及时Endlocal会造成超过最大允许递归层(xp下是32)
2,每次setlocal本地化时就开启了一个新的(子层)变量空间,并且保存新的变量变化,命令对变量的读写也在当前层(可从父层继承)。
而call返回后对变量的读写则回到了原来(父层)的变量空间。
最大递归层测试:
  1. @echo off
  2. for /l %%a in (1,1,33) do setlocal&echo 第 %%a 层
  3. pause
复制代码
各层之间的继承关系演示:
  1. @echo off
  2. set/a a=1,b=1,c=1
  3. echo 0:%a%,%b%,%c%
  4. call:a
  5. echo 0_:%a%,%b%,%c%
  6. pause&exit
  7. :a
  8. setlocal
  9. set a=2
  10. echo a:%a%,%b%,%c%
  11. call:b
  12. echo a_:%a%,%b%,%c%
  13. goto:eof
  14. :b
  15. setlocal
  16. set b=2
  17. echo b:%a%,%b%,%c%
  18. call:c
  19. echo b_:%a%,%b%,%c%
  20. goto:eof
  21. :c
  22. setlocal
  23. set c=2
  24. echo c:%a%,%b%,%c%
复制代码

[ 本帖最后由 hanyeguxing 于 2010-12-28 19:54 编辑 ]
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

参考:批处理最大限度原样输出含特殊字符的指定行内容
http://bbs.bathome.net/thread-4580-1-1.html
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

经测试,只要在子过程使用了 SetLocal 命令(以下任意一句)
    SetLocal
    SetLocal EnableDelayedExpansion
    SetLocal EnableExtensions
子过程中设置的值就不会返回。

为什么会这样呢?
在“SetLocal /?”的帮助中说到,如果在批处理中使用了 SetLocal 命令,那么在批处理结尾会有一个隐含的 ENDLOCAL 被执行。

所以原因应该就是,子过程也被当做是一个批处理的结束,所以当子过程中执行了 SetLocal,子过程结尾处就会执行 EndLocal。

[ 本帖最后由 tmplinshi 于 2010-12-28 14:38 编辑 ]
1

评分人数

TOP

  1. @echo off&setlocal enableDelayedExpansion
  2. for /l %%a in (1,1,8100) do set a=!a!0
  3. echo 完成初始化
  4. for /l %%a in (1,1,90000) do call:a %%a
  5. echo 完成测试
  6. pause&exit
  7. :a
  8. setlocal
  9. echo %1
  10. set #%1=%a%
复制代码
中间没有报任何错,显然子过程结束时执行了 EndLocal 。

[ 本帖最后由 hanyeguxing 于 2010-12-28 14:35 编辑 ]
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

你们两个还在讨论这个问题?
对Windows系统自带的手册(主要指Help目录下的东西,还包括虽不直接提供但微软网站可下载且很常用的,如script56.chm)一定要滚瓜烂熟,奸里面的确有很多好东西。

装操作系统一定要尽可能安装原版!集成补丁的也行,但不要装对系统改动太大的,更不要装精简版。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

  1. @echo off
  2. set a=ABC
  3. SetLocal EnableDelayedExpansion
  4. set a=IJK
  5. SetLocal DisableDelayedExpansion
  6. echo %a%
  7. pause
  8. call :A
  9. echo %a%
  10. pause
  11. goto :eof
  12. :A
  13. ::SetLocal EnableDelayedExpansion
  14. set a=OPQ
  15. ::SetLocal DisableDelayedExpansion
复制代码
我刚刚接触批处理不久?能帮我解释一下“::SetLocal EnableDelayedExpansion”这里的冒号什么意思吗?为什么运行结果会和上面一个代码不同,这双冒号起了什么作用?

TOP

本帖最后由 tmplinshi 于 2011-7-27 17:14 编辑

回复 7# ddddxxxxx


    双冒号是无效的标签。因为是标签,所以双冒号后面的是标签名;因为是无效标签,所以不会影响正常标签。总之,双冒号是用来注释的。

TOP

回复 8# tmplinshi


    谢谢斑竹解释。我又看了相关的东西  ,大致懂了。

TOP

原来如此,之前阅读一些代码总是看不懂,原来setlocal意义在这里,受教了。

TOP

返回列表