分类: LINUX
2013-11-13 00:20:32
::示例1
@echo off |
这个很简单,那么如果我们不用 %%i 来显示,而启用一个新的变量名 hanye 呢?
::示例2(错误)
@echo off |
运行结果并没有显示1到20,而是显示:ECHO 处于关闭状态。我们知道,出现这个显示,是因为
echo 后面什么也没有,如果跟了变量,则变量为空。那么,为什么变量为空了呢? set hanye=%%i 不是为变量赋值了吗?通过示例1,我们也知道 %%i 确实获得了数值。
在这里,我们要引入一个重要的概念——预处理机制:批处理读取命令时是按行读取的(另外例如 for
命令等,其后用一对圆括号闭合的所有语句也当作一行),在处理之前要完成必要的预处理工作,这其中就包括对该行命令中的变量赋值。在不启用变量延迟,也不对变量动态捕获其扩展变化时,变量在预处理阶段不作改变。
现在,我们看示例2:在 set hanye=%%i 和 echo %hanye% 之前,不存在变量 hanye
,即为空。而 set hanye=%%i 是在更改变量 hanye 的数值,这个更改在这一整句完成前不会生效。但 echo
%hanye% 却又处在生效完成前,即包括在预处理这一句的内部,所以无法显示新获取的值,就显示原来的值——空。
如果将 echo %hanye% 放在预处理之后,即 ) 的下面,我们就会看到 %hanye%
的数值,当然,这个时候只显示5。
回过头来,我们看示例1和示例2,变量 %%i 的数值由 for 直接赋值,在预处理时,%%i 的值并没有变化。
我们将示例2改成这样,就可以正常显示了:
::示例3
@echo off&setlocal enabledelayedexpansion |
开始批处理文件中环境变量的本地化。本地化将持续到出现匹配的 endlocal 命令或者到达批处理文件结尾为止。
语法
setlocal {enableextension | disableextensions}
{enabledelayedexpansion |
disabledelayedexpansion}
参数
注释
当您在脚本或批处理文件外使用 setlocal 时,将没有效果。
运行批处理文件时使用 setlocal 更改环境变量。运行 setlocal
后对环境所作的更改在批处理文件本地。Cmd.exe 在遇到 endlocal 命令或者到达批处理文件的结尾时将恢复上一次的设置。
setlocal 命令设置 ERRORLEVEL 变量。如果遇到 {enableextension |
disableextensions} 或 {enabledelayedexpansion |
disabledelayedexpansion},ERRORLEVEL 变量将设置成 0 (0)。否则,该变量将被设置成 1
(1)。在批处理脚本中使用该命令可以确定扩展是否可用,例如:
verify other 2>nul setlocal enableextensions if errorlevel 1 echo Unable to enable extensions
因为当禁用命令扩展时 cmd 不会设置 ERRORLEVEL 变量,所以当通过无效参数使用 setlocal 命令时
verify 命令将 ERRORLEVEL 变量初始化为非零值。另外,如果通过 {enableextension |
disableextensions} 或 {enabledelayedexpansion |
disabledelayedexpansion} 参数使用 setlocal 命令,而且没有将 ERRORLEVEL 变量设置成 1
(1) 时,则命令扩展将不可用。
结束批处理文件中环境更改的本地化,将环境变量还原为匹配 setlocal 命令前的值。
endlocal
setlocal enabledelayedexpansion
,就是启用变量延迟,我们可以形象的认为是启用了“对变量动态捕获扩展变化”。而 !
括起来的变量,就是要动态捕获扩展的目标变量,如果不需要,可以继续使用 % 括变量。
那么,什么情况下需要启用变量的延迟呢?在复合语句中,一旦变量需要发生扩展变化,就需要启用。
我们看一下示例4:
::示例4
@echo off&setlocal |
在预处理这一复合句时, set han=2
将在完成这一句时才生效。在没有完成这一句时,变量 han
的数值依然是1。现在,我们来看一个复杂点的复合句:
::示例5 显示数列01-20,并使用if判断
@echo off |
当 for 在第一次循环时,为 %%i 赋值为1,其后的 if %%i 时,使用的依然是这个数值;在 echo 0%%i
时也依然用1这个数值;在 echo %%i 时,还是用1这个数值。在整个预处理这一整句的过程中,
%%i 并没有发生变化,所以不需要变量延迟以动态扩展。现在,我们来他另一个批处理示例:
::示例6 显示数列01-20,并使用set补0
@echo off&setlocal enabledelayedexpansion |
在这一示例中,%%i 依然不需要动态变量扩展,因为他在预处理时不发生变化,但变量 han 则不同,他从空变成了有数值,发生了变化,所以需要变量延迟并动态扩展他。
需要说明一个问题,%%i
是可以被作为普通变量名使用的,上面的示例6就可以写成如下示例7:
::示例7
@echo off&setlocal enabledelayedexpansion |
但是,%%i 做为变量使用,并作为截取、替换、运算等时的变量名,仅限于为其赋值的 for 的 do ()的内部。
那么, set %%i=0%%i 和 echo !%%i:~-2! 可以用 &
连接起来吗?可以的,但问题也出来了,如下示例8:
::示例8(错误)
@echo off&setlocal enabledelayedexpansion |
运行后,仅显示一列的一位数字,那么那另一列的一位数哪去了呢?我们把 echo !%%i:~-2!
改成 echo !%%i:~-3! 就可以看到了。问题出在哪了呢?原来,当 set 与其他命令用 &
连接起来的时候,中间是不能有空格的,否则 set
会把空格当做给变量所赋的值的一部分。所以,示例8的正确写法如下:
示例9:
::示例9
@echo off&setlocal enabledelayedexpansion |
凡事皆有例外, set 和 %%i
也是如此。也就是说,不能有这样的表但式: set /a %%i=%%i+10 , %%i 不能在 set /a
中做设置的变量名,否则提示错误“运算符不存在。”。必须写成: set /a
hanye=%%i+10 。如下示例:迭代-3到1(步长为1),并将每个结果再加10,然后为1-9前补0。
::示例10
@echo off&setlocal enabledelayedexpansion |