有两个文件,output.txt和test.bat。在output.txt中,只有一行'1 2 3 4',test.bat的内容是
@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'。 奇怪的?错误?
答案 0 :(得分: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%
这只是一个命令,因此变量在运行之前只展开一次(特别是,它们不会在SET
之后和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
之间进行扩展,则可以通过分解块来实现扩展。您可以通过使用NOT
反转测试并使用GOTO
跳过“成功”分支中较早的代码来执行此操作:
SET foo=
ECHO foo = %foo%
IF NOT 1==1 GOTO :proceed
SET foo=bar
ECHO foo = %foo%
:proceed
以上脚本也会输出:
foo =
foo = bar
这两种方法都转化为:
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
答案 1 :(得分:2)
不是错误 - 这是CMD如何实现变量扩展的副作用。 Raymond Chen在这里有一篇文章:
http://blogs.msdn.com/b/oldnewthing/archive/2006/08/23/714650.aspx
具体来说,在您的第一个示例中,从展开%variable%
开始,它从未被设置过。