批处理文件无法在条件语句中设置环境变量

14
为什么下面的Windows批处理文件输出Foo后跟Bar,而不是Baz
@echo off
setlocal

set _=Foo
echo %_%
set _=Bar
if 1==1 (
    set _=Baz
    echo %_%
)

我的系统输出(Microsoft Windows XP [Version 5.1.2600])是:

Foo
Bar
如果我去掉条件语句,就会看到预期的FooBaz的输出。

BAT文件中的作用域问题奇怪。 - Nick Fortescue
3个回答

29

正在发生的是变量替换是在读取一行时完成的。你没有考虑到的事实是:

if 1==1 (
    set _=Baz
    echo %_%
)

one "line" 实际是一行,尽管你可能认为它不是。在 set 语句之前,"%_%" 的扩展已经完成。

你需要延迟扩展。几乎我所有的命令脚本都会以 "setlocal enableextensions enabledelayedexpansion" 开头,以便充分利用 cmd.exe 的全部功能。

因此,我的脚本版本将是:

@echo off
setlocal enableextensions enabledelayedexpansion

set _=Foo
echo !_!
set _=Bar
if 1==1 (
    set _=Baz
    echo !_!
)

endlocal

这样生成的代码将是正确的:"Foo", "Baz",而不是 "Foo", "Bar"


2
太棒了,感谢详细的解释。我认为我再次遇到了这个确切的限制,但是在这里受到了更严格的环境限制:https://dev59.com/kUfRa4cB1Zd3GeqP-qLp。不幸的是,如果我使用MSBuild Exec任务,我没有打开命令扩展的能力...嗯... - Daniel Fortunov

4
答案和这个问题的答案相同:批处理文件中奇怪的作用域问题。请参阅该链接以获取更多详细信息。基本上,变量扩展是在行读取时间而不是执行时间完成的。

3

试一下这个

@echo off
setlocal

set _=Foo
echo %_%
set _=Bar
if "1" NEQ "2" goto end
set _=Baz
echo %_%
:end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接