'for'语句在Windows批处理(.bat)文件中的'if'语句中打包时很奇怪
有两个文件output.txt和test.bat。在output.txt的,只有一个线, '1 2 3 4' 和test.bat的含量是'for'语句在Windows批处理(.bat)文件中的'if'语句中打包时很奇怪
@echo off
set condition=1
if "%condition%" == "1" (
for /F "tokens=1,2,3,4* delims= " %%a in (output.txt) do set variable=%%a
echo %variable%
)
pause
运行test.bat的将回声什么。但是如果我稍微改变它,可以看到:
@echo off
set condition=1
for /F "tokens=1,2,3,4* delims= " %%a in (output.txt) do set variable=%%a
echo %variable%
if "%condition%" == "1" (
for /F "tokens=1,2,3,4* delims= " %%a in (output.txt) do set variable=%%a
echo %variable%
)
pause
它会回显“1”两次。 奇怪?错误?
我不认为这两个脚本中的任何一个都会执行您认为它的操作(具体而言,第二个脚本的工作原理只是因为您在第一个脚本之后运行它)。
为什么它的行为如此?
需要注意的重要一点是,除非延迟变量扩展打开,否则将在该命令执行前为每个命令评估变量。这在使用IF
时尤其关键,因为parens内的整个命令块被视为一个命令。
举例说明:
SET foo=
ECHO foo = %foo%
IF 1==1 (
SET foo=bar
ECHO foo = %foo%
)
以上脚本的输出:
foo =
foo =
的原因是条件相当于
IF 1==1 SET foo=bar && ECHO foo = %foo%
这只是一个命令,所以变量在它运行之前只扩展一次(特别是在之后它们不会扩展和之前的ECHO
)。
这也是在你的脚本中发生的事情。由于%variable%
设置为和在块内回显,所以ECHO
实际上在块输入之前的值为%variable%
,因此您看不到“当前”值。
如何解决?
解决延迟变量扩展问题
有两种方法可以解决这个问题。直截了当一个是使延迟变量扩展与SETLOCAL
,然后参考变量的语法的!var!
代替%var%
:
SETLOCAL ENABLEDELAYEDEXPANSION
SET foo=
ECHO foo = !foo!
IF 1==1 (
SET foo=bar
ECHO foo = !foo!
)
以上脚本将输出:
foo =
foo = bar
通过破坏解决问题命令块
还有另一种方法:记住变量在每个命令(或块)执行之前扩展一次。因此,如果您想要在SET
和ECHO
之间进行扩展,您可以通过分解该块来解决这个问题。
SET foo=
ECHO foo = %foo%
IF NOT 1==1 GOTO :proceed
SET foo=bar
ECHO foo = %foo%
:proceed
以上脚本也将输出:
foo =
foo = bar
应用可以通过逆转与NOT
测试和使用GOTO
可以跳过前面是“成功的”分支中的代码做到这一点解决你的例子
这两种方法转化为可以在本:
SETLOCAL ENABLEDELAYEDEXPANSION
IF "%condition%" == "1" (
FOR /F "tokens=1,2,3,4* delims= " %%a in (output.txt) DO SET variable=%%a
ECHO !variable!
)
或者这个:
IF NOT "%condition%" == "1" GOTO :proceed
FOR /F "tokens=1,2,3,4* delims= " %%a in (output.txt) DO SET variable=%%a
ECHO %variable%
:proceed
不是一个错误 - 这是CMD如何实现可变扩展的副作用。雷蒙德陈上有一篇文章在这里:
http://blogs.msdn.com/b/oldnewthing/archive/2006/08/23/714650.aspx
具体而言,在你的第一个例子中,当%variable%
展开的,它从来没有被设置。