2009-05-18 25 views
14

Tại sao tệp Windows Batch Tệp sau đây xuất hiện Foo theo sau là Bar, thay vì Baz?Tệp hàng loạt không đặt biến môi trường trong câu lệnh điều kiện

@echo off 
setlocal 

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

Sản lượng trên hệ thống của tôi (Microsoft Windows XP [Version 2600/05/01]) là:

Foo 
Bar 

Nếu tôi loại bỏ các tuyên bố có điều kiện, sản lượng dự kiến ​​của FooBaz được quan sát.

+0

Bản sao của http://stackoverflow.com/questions/305605/weird-scope-issue-in-bat-file –

Trả lời

28

Điều đang xảy ra là thay thế biến được thực hiện khi đọc một dòng. Những gì bạn đang thất bại trong việc đưa vào tài khoản là một thực tế rằng:

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

một "dòng", bất chấp những gì bạn có thể nghĩ. Việc mở rộng "%_%" được thực hiện trước tuyên bố set.

Điều bạn cần là mở rộng chậm trễ. Chỉ cần mỗi một kịch bản lệnh của tôi bắt đầu bằng "setlocal enableextensions enabledelayedexpansion" để sử dụng toàn bộ sức mạnh của cmd.exe.

Vì vậy, phiên bản của tôi về kịch bản sẽ là:

@echo off 
setlocal enableextensions enabledelayedexpansion 

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

endlocal 

này tạo đúng "Foo", "Baz" hơn "Foo", "Bar".

+2

Tuyệt vời, cảm ơn lời giải thích chi tiết. Tôi nghĩ rằng tôi đang đi lên chống lại giới hạn chính xác này một lần nữa, nhưng trong một môi trường hạn chế hơn ở đây: http://stackoverflow.com/questions/879023/honoring-exit-codes-from-batch-files-invoked-by- msbuild Thật không may là tôi không có khả năng bật các lệnh mở rộng nếu tôi đang sử dụng tác vụ MSBuild 'Exec' ... hmmm ... –

3

thử này

@echo off 
setlocal 

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

Câu trả lời cho điều này là giống như câu trả lời cho: Weird scope issue in batch file. Xem ở đó để biết thêm chi tiết. Về cơ bản mở rộng biến được thực hiện tại thời gian đọc dòng, không phải tại thời gian thực hiện.

Các vấn đề liên quan