2012-07-05 40 views
0

有两个文件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”两次。 奇怪?错误?

回答

4

我不认为这两个脚本中的任何一个都会执行您认为它的操作(具体而言,第二个脚本的工作原理只是因为您在第一个脚本之后运行它)。

为什么它的行为如此?

需要注意的重要一点是,除非延迟变量扩展打开,否则将在该命令执行前为每个命令评估变量。这在使用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 

通过破坏解决问题命令块

还有另一种方法:记住变量在每个命令(或块)执行之前扩展一次。因此,如果您想要在SETECHO之间进行扩展,您可以通过分解该块来解决这个问题。

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