Windows 7 批处理文件:为什么这些 IF 块阻止我将变量分配给值?

osc*_*tin 7 prompt batch-file

这是损坏的批处理文件:

@echo off
if prod==prod (
    if xps==xps (
        set i1=prodxpsi1
        set i2=prodxpsi2
        set e1=prodxpse1
        set e2=prodxpse2
    ) else (
        set i1=prodzpsi1
        set i2=prodzpsi2
        set e1=prodzpse1
        set e2=prodzpse2
    )

    if 1==1 (
        echo %i1%, %i2%, %e1%, %e2%
    ) else (
        echo %i1%, %i2%, %e1%, %e2%
    )
)

pause
Run Code Online (Sandbox Code Playgroud)

但是,当我if prod==prod像这样取出外部块时,它可以工作:

@echo off
if xps==xps (
    set i1=prodxpsi1
    set i2=prodxpsi2
    set e1=prodxpse1
    set e2=prodxpse2
) else (
    set i1=prodzpsi1
    set i2=prodzpsi2
    set e1=prodzpse1
    set e2=prodzpse2
)

if 1==1 (
    echo %i1%, %i2%, %e1%, %e2%
) else (
    echo %i1%, %i2%, %e1%, %e2%
)

pause
Run Code Online (Sandbox Code Playgroud)

当我第一次运行批处理文件时,它回显, , ,. 当我第二次运行它时,它工作正常:

洛尔乌特

Han*_*ood 5

这是命令解析器的一个怪癖。由于括号的存在,它将从if ...到的所有内容都)视为一行。当它读取此“一行”时,它会在处理任何变量之前将所有变量扩展为其值。这些set命令都发生在变量被扩展之后。

有两种解决方案:分支和延迟扩展。

分支:确保set命令和echo命令不在同一组最顶层括号中:

@echo off
if not prod==prod goto :end
if xps==xps (
    set ...
) else (
    set ...
)
if 1==1 (
    ...
)
:end
pause
Run Code Online (Sandbox Code Playgroud)

延迟扩展:这会导致变量按需扩展,而不是提前扩展。使用命令SetLocal EnableDelayedExpansion激活此模式,使用!标记以这种方式引用变量,并EndLocal在完成后使用该命令。请注意,EndLocal不会忘记任何变量后声明SetLocal,所以你可能要移动SetLocal到后set命令。

@echo off
setlocal enabledelayedexpansion
if prod==prod (
    if xps==xps (
        set i1=prodxpsi1
        ...
    ) else (
        set i1=prodzpsi1
        ...
    )
    if 1==1 (
        echo !i1!, !i2!, !e1!, !e2!
    ) else (
        echo !i1!, !i2!, !e1!, !e2!
    )
)
endlocal
pause
Run Code Online (Sandbox Code Playgroud)