Пакетный файл не может установить переменную среды в условном выражении

Почему следующий пакетный файл Windows выводит Foo после Bar, а не Baz?

@echo off
setlocal

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

Вывод в моей системе (Microsoft Windows XP [Версия 5.1.2600]):

Foo
Bar

Если я удаляю условный оператор, ожидаемый результат Foo и Baz наблюдается.

Ответы

Ответ 1

Что происходит в том, что замена переменных выполняется при чтении строки. То, что вы не учитываете, это тот факт, что:

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

- это одна "линия", несмотря на то, что вы думаете. Расширение "%_%" выполняется перед оператором set.

Что вам нужно, это отсроченное расширение. Почти каждый из моих командных скриптов начинается с "setlocal enableextensions enabledelayedexpansion", чтобы использовать полную мощность cmd.exe.

Итак, моя версия script будет:

@echo off
setlocal enableextensions enabledelayedexpansion

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

endlocal

Это генерирует правильный "Foo", "Baz", а не "Foo", "Bar".

Ответ 2

Ответ на этот вопрос совпадает с ответом на: странная проблема с областью в пакетном файле. См. Там для более подробной информации. В основном переменное расширение выполняется во время чтения строки, а не во время выполнения.

Ответ 3

попробуйте это

@echo off
setlocal

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