先看代码:- @echo off
- set str=!abc!
- set !abc!=ok
- echo %str%
- set abc=sss
- setlocal enabledelayedexpansion
- call echo %%!str!%%
- endlocal
- pause
复制代码 运行结果为:复制代码 下面是解释:
第二句 因为没有开启变量延迟,所以变量str的值为字符串!abc!
第三句 设置变量!abc!的值为字符串ok ,注意这个变量包含感叹号!
第四句 显示变量str的值,因为没有开启变量延迟,所以输出!abc!
第五i句 无需解释
第六句 开启变量延迟
第七句 关键句,下面是详细解释:
cmd在预处理 call %%!str!%%时,第一步是替换%var%类型的变量,这里没有这种变量,所以不做任何处理。第二步,由于变量延迟扩展的特性,在执行到 call echo %%!str!%% 时,才替换!str!为!abc!,这是这句代码就变成了call echo %%!abc!%%,这时,第三步开始了,是处理call命令,这时代码变成了echo %!abc!%,第四步,显示变量!abc!的值,就输出ok了,注意这里只会处理%var%之类的变量,而不处理!var!之类的变量。
再看下面的代码:- @echo off
- set str=!abc!
- set !abc!=ok
- set abc=sss
- setlocal enabledelayedexpansion
- call :t
- endlocal
- pause
-
- :t
- echo %%!str!%%
- goto :eof
复制代码 运行结果为:复制代码 下面是解释:
因为有些代码前面已经解释过了,这里不再解释。
执行到call :t 这句时,cmd将读取 echo %%!str!%% ,然后进行预处理,第一步,替换%var%之类的变量,这里没有,就跳过。第二步,替换!var!之类的变量,代码就变成 echo %%!abc!%%,然后就输出 %!abc!%了。
总结:
开启变量延迟后,对于复制代码 预处理一般是先替换%var%之类的变量,然后等执行到有!var!的代码时,替换!var!,之后,处理call命令,将%%变成%,最后,再替换%var%之类的变量,然后直接输出,而不会去处理!var!之类的字符串。对于- setlocal enabledelayedexpansion
- call :t
- endlocal
- pause
-
- :t
- echo %%!str!%%
- goto :eof
复制代码 将%%变成%不是call的原因,这里的call其实和goto的作用是一样的,只不过是用call时,执行完所调用的程序代码后还可以回来,而goto不行。这样cmd处理echo %%!str!%%就很简单了,替换!str!同时把%%变成%后直接输出。 |