Board logo

标题: setlocal EnableDelayedExpansion 命令咨询 [打印本页]

作者: start    时间: 2008-8-21 09:36     标题: setlocal EnableDelayedExpansion 命令咨询

看到别人写代码都会用setlocal EnableDelayedExpansion这个语句,可是不知道是什么意思.
用了和没和用有什么样的区别呢,
用别的人代码把这句删了就出错了...

[ 本帖最后由 start 于 2008-8-21 10:21 编辑 ]
作者: pusofalse    时间: 2008-8-21 09:40

环境变量延迟扩展的作用啊,非常重要。
作者: 基拉freedom    时间: 2008-8-21 11:33

这个也有缺陷
用得多了 就会提示错误 显示扩充达到最大值~~~~
作者: namejm    时间: 2008-8-21 11:39

  这个问题问到了点子上,问得相当好,我都等了好久,今天终于有人在问了^_^

  这条语句的意思是:启用变量延迟。

  什么情况先应该使用变量延迟?请看 willsort 在CN-DOS给我的回复(地址:http://www.cn-dos.net/forum/viewthread.php?tid=20733):
      关于环境变量延迟扩展,使用set /?可以查看到部分说明,不过考虑到其粗劣的翻译水平,建议在查看之前,首先chcp 437切换为英文查看原英文说明。鉴于文中已说得十分详尽,而且有数个代码示例,应该不难理解。在此仅略作一些补充。

      在许多可见的官方文档中,均将使用一对百分号闭合环境变量以完成对其值的替换行为称之为“扩展(expansion)”,这其实是一个第一方的概念,是从命令解释器的角度进行称谓的,而从我们使用者的角度来看,则可以将它看作是引用(Reference)、调用(Call)或者获取(Get)。

      而命令解释器是扩展环境变量的行为大致如下:首先读取命令行的一条完整语句,在进行一些先期的预处理之后,命令被解释执行之前,会对其中用百分号闭合的字符串进行匹配,如果在环境空间中找到了与字符串相匹配的环境变量,则用其值替换掉原字符串及百分号本身,如果未得到匹配,则用一个空串替换,这个过程就是环境变量的“扩展”,它仍然属于命令行的预处理范畴。

      而一条“完整的语句”,在NT的命令解释器CMD中被解释为“for if else”等含有语句块的语句和用“& | && ||”等连接起来的复合语句。

      因此,当CMD读取for语句时,其后用一对圆扩号闭合的所有语句将一同读取,并完成必要的预处理工作,这其中就包括环境变量的扩展,所以在for中的所有语句执行之前,所有的环境变量都已经被替换为for之前所设定的值,从而成为一个字符串常量,而不再是变量。无论在for中将那些环境变量如何修改,真正受到影响的只是环境变量空间,而非for语句内部。
      
      而为了能够在for语句内部感知环境变量的动态变化,CMD设计了延迟的环境变量扩展特性,也就是说,当CMD读取了一条完整的语句之后,它不会立即执行变量的扩展行为,而会在某个单条语句执行之前再进行扩展,也就是说,这个扩展行为被“延迟”了。

      延迟环境变量扩展特性在CMD中缺省是关闭的,开启它的方法目前有两个:一是CMD /v:off(此处说法有误,应为 CMD /v:on——namejm 注),它会打开一个新的命令行外壳,在使用exit退出这个外壳之前,扩展特性始终有效,常用于命令行环境中;二是setlocal EnableDelayedExpansion,它会使环境变量的修改限制到局部空间中,在endlocal之后,扩展特性和之前对环境变量的修改将一同消失,常用于批处理语句中。

作者: namejm    时间: 2008-8-21 11:43

原帖由 基拉freedom 于 2008-8-21 11:33 发表
这个也有缺陷
用得多了 就会提示错误 显示扩充达到最大值~~~~

  你可能用在for语句内部或者goto循环中,使得 setlocal enabledelayedexpansion 语句被执行了32次以上——当 setlocal 语句被执行32次以上时,就会达到它的最大递归层,从而引发错误。避免这个错误的办法就是:避免在for中或goto循环中的执行次数超过32次,或者在超过32次前用 endlocal 终止 setlocal 。
作者: start    时间: 2008-8-21 12:18

好像明白了一点,又好像一点也不明白。
是不是说他的作用是为了防止某一个命令使用的次数过而出错?
作者: pusofalse    时间: 2008-8-21 12:30     标题: 回复 6楼 的帖子

测试如下两段代码:
  1. @echo off
  2. for /l %%a in (1 1 50) do (
  3.         set num=%%a
  4.         setlocal enabledelayedexpansion
  5.         echo !num!
  6. )
  7. pause
复制代码
  1. @echo off
  2. for /l %%a in (1 1 50) do (
  3. set num=%%a
  4. setlocal enabledelayedexpansion
  5. echo !num!
  6. endlocal
  7. )
  8. pause
  9. pause
复制代码

作者: start    时间: 2008-8-21 12:41

是说setlocal enabledelayedexpansion 只是一个参数而不是一个完整的命令吗
作者: qinshenyizhong    时间: 2010-7-16 16:07

这问题好啊 我也有点 搞不懂 有好多人在代码的开头 写 setlocal EnableDelayedExpansion 有什么用呢? 麻烦高手解答一下 谢谢
作者: 随风    时间: 2010-7-16 16:19

搜索变量延迟
作者: wc726842270    时间: 2010-8-27 20:58

不过个人建议。先看一下预处理机制.比较好
作者: cjiabing    时间: 2010-8-27 21:32

用实例说话:
  1. @echo off
  2. echo.
  3. echo     1、启用变量延迟之前——成功  
  4. echo.
  5. for /f  "tokens=*" %%i in ("中华人民共和国万岁 万岁 万万岁") do echo %%i
  6. pause>nul
  7. echo.
  8. echo     2、启用变量延迟之前——失败
  9. echo.
  10. for /f  "tokens=*" %%i in ("中华人民共和国万岁 万岁 万万岁") do (
  11. set var=%%i
  12. echo %var%
  13. )
  14. pause>nul
  15. setlocal EnableDelayedExpansion
  16. echo.
  17. echo     3、启用变量延迟之后——失败
  18. echo.
  19. for /f  "tokens=1,2,3" %%i in ("中华人民共和国万岁 万岁 万万岁") do (
  20. set var1=%%i
  21. set var2=%%j
  22. set var3=%%k
  23. echo %var1% %var2% %var3%
  24. )
  25. pause>nul
  26. setlocal EnableDelayedExpansion
  27. echo.
  28. echo     4、启用变量延迟之后——成功
  29. echo.
  30. for /f  "tokens=1,2,3" %%i in ("中华人民共和国万岁 万岁 万万岁") do (
  31. set var1=%%i
  32. set var2=%%j
  33. set var3=%%k
  34. echo !var1! !var2! !var3!
  35. )
  36. pause>nul
  37. echo _________________________________________________________________
  38. echo.
  39. echo      启用变量延迟:
  40. echo      1、启用之前使用“setlocal EnableDelayedExpansion”声明/开启。
  41. echo      2、启用变量延迟之后,变量的百分号要换成感叹号。
  42. echo.
  43. echo      为什么用“set var=%%i”转换变量?
  44. echo      因为有些情况下用“%%i”无法或不方便命令执行。
  45. echo      变量延迟就是预先设置(set)好变量(%var%)再执行后面的命令(echo)
  46. echo      说白了,就是给命令设置一个可以执行的前提条件。
  47. echo      变量延迟经常和FOR和SET混在一起,必须好好学学。
  48. echo.      
  49. pause>nul
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2