2009-05-18 3 views
14

Perché il seguente file batch di Windows viene emesso seguito da Bar anziché Baz?Il file batch non riesce a impostare la variabile di ambiente nell'istruzione condizionale

@echo off 
setlocal 

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

L'uscita sul mio sistema (Microsoft Windows XP [Versione 5.1.2600]) è:

Foo 
Bar 

Se rimuovo l'istruzione condizionale, i risultati attesi di Foo e Baz si osserva.

+0

Duplicato di http://stackoverflow.com/questions/305605/weird-scope-issue-in-bat-file –

risposta

28

Quello che succede è che la sostituzione delle variabili avviene quando viene letta una linea. Quello che stai omettendo di prendere in considerazione è il fatto che:

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

è una "linea", nonostante quello che si potrebbe pensare. L'espansione di "%_%" viene eseguita prima dello l'istruzione set.

Quello che ti serve è un'espansione ritardata. Quasi tutti i miei script di comando iniziano con "setlocal enableextensions enabledelayedexpansion" in modo da utilizzare tutta la potenza di cmd.exe.

Quindi la mia versione dello script sarebbe:

@echo off 
setlocal enableextensions enabledelayedexpansion 

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

endlocal 

Questo genera il corretto "Foo", "Baz" piuttosto che "Foo", "Bar".

+2

Impressionante, grazie per la spiegazione dettagliata. Penso di trovarmi di nuovo contro questo limite esatto, ma in un ambiente più ristretto qui: http://stackoverflow.com/questions/879023/honoring-exit-codes-from-batch-files-invoked-by- msbuild Sfortunatamente non ho la possibilità di attivare le estensioni dei comandi se sto usando il task 'Exec' di MSBuild ... hmmm ... –

3

provare questo

@echo off 
setlocal 

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

La risposta a questa è la stessa come la risposta a: Weird scope issue in batch file. Vedi lì per maggiori dettagli. L'espansione sostanzialmente variabile viene eseguita al tempo di lettura della riga, non al momento dell'esecuzione.