Umgebungsvariablen in Stapeldateien werden erweitert, wenn eine Zeile analysiert wird. Bei Blöcken, die durch (Ihre if defined
) Klammern begrenzt sind , zählt der gesamte Block als "Zeile" oder Befehl.
Dies bedeutet, dass alle Vorkommen von% FOO% durch ihre Werte ersetzt werden, bevor der Block ausgeführt wird. In deinem Fall mit nichts, da die Variable noch keinen Wert hat.
Um dies zu lösen, können Sie die verzögerte Erweiterung aktivieren :
setlocal enabledelayedexpansion
Eine verzögerte Erweiterung bewirkt, dass durch Ausrufezeichen ( !
) begrenzte Variablen bei der Ausführung ausgewertet werden, anstatt sie zu analysieren, wodurch das richtige Verhalten in Ihrem Fall sichergestellt wird:
if not defined BAR (
set FOO=1
echo Foo: !FOO!
)
help set
Details dazu auch:
Schließlich wurde die Unterstützung für die verzögerte Erweiterung von Umgebungsvariablen hinzugefügt. Diese Unterstützung ist standardmäßig immer deaktiviert, kann jedoch über die /V
Befehlszeilenoption aktiviert / deaktiviert werden CMD.EXE
. SehenCMD /?
Die verzögerte Erweiterung von Umgebungsvariablen ist hilfreich, um die Einschränkungen der aktuellen Erweiterung zu umgehen, die beim Lesen einer Textzeile und nicht beim Ausführen auftreten. Das folgende Beispiel zeigt das Problem mit der sofortigen Variablenerweiterung:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)
würde die Nachricht niemals anzeigen, da die Anweisung %VAR%
in beiden IF
Anweisungen beim Lesen der ersten IF-Anweisung ersetzt wird, da sie logisch den Hauptteil der IF
Anweisung enthält , bei der es sich um eine zusammengesetzte Anweisung handelt. Das IF in der zusammengesetzten Anweisung vergleicht also wirklich "Vorher" mit "Nachher", was niemals gleich sein wird. In ähnlicher Weise funktioniert das folgende Beispiel nicht wie erwartet:
set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%
dadurch wird keine Liste der Dateien im aktuellen Verzeichnis erstellt, sondern lediglich die LIST
Variable auf die zuletzt gefundene Datei gesetzt. Dies ist wiederum darauf zurückzuführen, dass das %LIST%
Attribut nur einmal erweitert wird, wenn die FOR
Anweisung gelesen wird. Zu diesem Zeitpunkt ist die LIST
Variable leer. Die eigentliche FOR-Schleife, die wir ausführen, lautet also:
for %i in (*) do set LIST= %i
das setzt nur LIST
auf die zuletzt gefundene Datei.
Mit der verzögerten Erweiterung von Umgebungsvariablen können Sie zur Ausführungszeit Umgebungsvariablen mit einem anderen Zeichen (dem Ausrufezeichen) erweitern. Wenn die verzögerte Variablenerweiterung aktiviert ist, können die obigen Beispiele wie folgt geschrieben werden, um wie beabsichtigt zu funktionieren:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo If you see this, it worked
)
set LIST=
for %i in (*) do set LIST=!LIST! %i
echo %LIST%
!
, verwenden Sie^^^!
(es zweimal zu entkommen). Andernfalls wird die "verzögerte Erweiterung" -Funktion es essen.Das gleiche Verhalten tritt auch auf, wenn sich die Befehle in einer einzelnen Zeile befinden (
&
ist das Befehlstrennzeichen):Joeys Erklärung ist meine Lieblingserklärung. Beachten Sie jedoch, dass
enabledelayedexpansion
dies unter Windows NT 4.0 nicht funktioniert (und ich bin mir bei Windows 2000 nicht sicher).Über Ihre Follow-up - Frage, nein, ist es nicht möglich,
EnableDelayedExpansion
ohnesetlocal
. Das ursprüngliche Verhalten, mit dem Sie konfrontiert wurden, kann jedoch verwendet werden, um dieses zweite Problem zu umgehen: Der Trick besteht darin,endlocal
in derselben Zeile die Werte der benötigten Variablen erneut festzulegen.Hier ist Ihre
test.bat
modifizierte:Hier ist eine andere Problemumgehung: Verwenden Sie eine Prozedur in derselben Datei anstelle eines Inline-Blocks oder einer externen Datei.
quelle
Wenn dies nicht der Fall ist, haben Sie wahrscheinlich die Erweiterung der Umgebungsvariablen verzögert. Sie können es entweder mit ausschalten
cmd /V:OFF
oder Ausrufezeichen in Ihrem verwenden, wenn:quelle
Dies geschieht, weil Ihre Zeile mit dem
FOR
Befehl nur einmal ausgewertet wird. Sie brauchen eine Möglichkeit, es neu zu bewerten. Sie können eine verzögerte Erweiterung mit folgendemCALL
Befehl simulieren :quelle
Es ist erwähnenswert, dass es funktioniert, wenn es ein einzelner Befehl in derselben Zeile ist.
z.B
wird tatsächlich
FOO
auf 1 gesetzt. Sie könnten dann eine weitere Überprüfung durchführen, z.Hey, ich habe nie gesagt, dass es hübsch ist. Aber wenn Sie sich nicht mit Setlocal oder dem verzögerten Expansionsgeschäft herumschlagen möchten, können Sie dies schnell umgehen.
quelle
Manchmal, wie ich es in meinem Fall getan habe, benötigen Sie möglicherweise eine alternative Lösung, wenn Sie mit älteren Systemen wie alten NT4-Servern kompatibel sein müssen, auf denen eine verzögerte Erweiterung nicht funktioniert oder aus irgendeinem Grund nicht funktioniert.
Falls Sie die Delayd-Erweiterung verwenden, wird auch empfohlen, mindestens den Check-in-Batch einzuschließen:
Für den Fall, dass Sie einfachere und übersichtlichere Vorgehensweisen wünschen, finden Sie hier alternative Lösungen:
was so funktioniert:
und noch eine reine cmd-lösung:
es funktioniert so:
und das ist voll, wenn dann andere Syntax-Lösung:
es funktioniert so:
quelle