Never save something for a special occasion. Every day in your life is a special occasion.
分类:
2010-11-17 22:19:16
什么是延迟变量扩展?
变量是程序中基本元素,所谓变量...不用解释吧!但在bat中你可能发现“变量”并不总是如期工作,如下代码,你觉得它会输出什么呢?
@echo off
set v=valuel&echo %v%
pause
执行后显示“ECHO 处于关闭状态”——不是应该显示value吗?要解释这个问题,你得明白cmd.exe解释器的“变量扩展”过程。
下面是高手的帖子,已经解释得很清楚了。
willsort:
关于环境变量延迟扩展,使用set /?可以查看到部分说明,如果你觉得翻译水平精力,可以先chcp 437切换为英文再查看英文说明。
你常常会看到一对百分号包围起来的环境变量这称为“扩展(expansion)”,这个概念是从命令解释器的角度进行称谓的,从我们使用者的角度来看叫引用(Reference)。
命令解释器扩展环境变量的行为大致如下:
首先读取命令行的一条完整语句,在进行一些先期的预处理之后,命令被解释执行之前,会对其中用百分号闭合的字符串进行匹配。如果在环境空间中找到了与字符串相匹配的环境变量,则用其值替换掉原字符串及百分号本身;如果未得到匹配,则用一个空串替换。这个过程就是环境变量的“扩展”,它仍然属于命令行的预处理范畴。
所谓一条“完整的语句”,在NT的命令解释器CMD中被解释为“for if else”等含有语句块的语句和用“& | && ||”等连接起来的复合语句。
因此,当CMD读取for语句时,其后用一对圆扩号闭合的所有语句将一同读取,并完成必要的预处理工作,这其中就包括环境变量的扩展。所以在for中的所有语句执行之前,所有的环境变量都已经被替换为for之前所设定的值,从而成为一个字符串常量——不再是变量!无论在for中将那些环境变量如何修改,真正受到影响的只是环境变量空间,而非for语句内部。
为了能够在for语句内部感知环境变量的动态变化,CMD设计了延迟的环境变量扩展特性——也就是说,当CMD读取了一条完整的语句之后,它不会立即执行变量的扩展行为——而会在某个单条语句执行之前再进行扩展,也就是说,这个扩展行为被“延迟”了。
延迟环境变量扩展特性在CMD中缺省是关闭的,开启它的方法目前有两个:一是CMD /v:on,它会打开一个新的命令行外壳,在使用exit退出这个外壳之前,扩展特性始终有效,常用于命令行环境中;二是setlocal EnableDelayedExpansion,它会使环境变量的修改限制到局部空间中,在endlocal之后,扩展特性和之前对环境变量的修改将一同消失,常用于批处理语句中。