Sonderbare Umfang Problem in .bat-Datei
-
08-07-2019 - |
Frage
Ich schreibe eine einfache .bat-Datei, und ich habe in einige seltsame Verhalten führen. Es gibt ein paar Orte, wo ich eine einfache if / anderes zu tun haben, aber der Code innerhalb der Blöcke scheinen nicht richtig zu funktionieren.
Hier ist ein einfacher Fall, der den Fehler zeigt:
@echo off
set MODE=FOOBAR
if "%~1"=="" (
set MODE=all
echo mode: %MODE%
) else (
set MODE=%~1
echo mode: %MODE%
)
echo mode: %MODE%
Der Ausgang Ich erhalte ist:
C:\>test.bat test
mode: FOOBAR
mode: test
Warum ist das Echo in dem Codeblock den neuen Wert der Variablen nicht bekommen? In dem eigentlichen Code Ich schreibe ich brauche ein paar Variablen erstellen und sie in dem Rahmen der if / else verweisen. Ich konnte schalten diese Etiketten zu verwenden und gotos anstelle eines if / else, aber das scheint nicht annähernd so sauber.
Was sind die Ursachen dieses Verhalten? Gibt es irgendeine Art von Limit auf Variablen innerhalb Codeblöcke?
Lösung
Sie führen in das Problem der statischen Variablen Expansion cmd. Die Variable MODE wird nur einmal ausgewertet. Sie können das sehen, wenn Sie das @ echo off line weglassen.
Aus der Menge /? Dokumentation:
Schließlich Unterstützung für die verzögerte Erweiterung von Umgebungsvariablen hat hinzugefügt. Diese Unterstützung ist immer standardmäßig deaktiviert, kann aber sein, aktiviert / über den / V-Befehl Behinderte Leitungsschalter nach CMD.EXE. Siehe CMD /?
Verzögerte Erweiterung von Umgebungsvariablen ist nützlich für die Fortbewegung die Grenzen des aktuellen Expansion, die der, wenn eine Linie passiert, Text gelesen wird, nicht, wenn es ausgeführt wird. Das folgende Beispiel zeigt die Problem mit sofortigem Variable Expansion:
set VAR=before if "%VAR%" == "before" ( set VAR=after if "%VAR%" == "after" @echo If you see this, it worked )
würde nie die Nachricht anzuzeigen, da das% VAR% in IF-Anweisungen BEIDE ist wenn der erste substituierte IF Anweisung gelesen wird, da es logisch weist der Körper des IF, das ist eine zusammengesetzte Anweisung. So ist die IF innerhalb der zusammengesetzten Anweisung ist wirklich zu vergleichen „vor“ mit „nach“ die nie gleich sein. Ähnlich, Im folgenden Beispiel wird nicht funktionieren wie erwartet:
set LIST= for %i in (*) do set LIST=%LIST% %i echo %LIST%
, dass es baut keine Liste Dateien im aktuellen Verzeichnis, aber stattdessen setzen nur die LIST Variable in die letzte Datei gefunden. Auch dies ist, weil die% LIST% ist erweitert nur einmal, wenn die FOR Anweisung gelesen wird, und zu diesem Zeitpunkt die LIST Variable ist leer. so ist die Ist FOR-Schleife ist, die wir ausführen:
for %i in (*) do set LIST= %i
, die nur Liste Einstellung auf das hält letzte Datei gefunden.
Verzögerte Erweiterung von Umgebungsvariablen Damit können Sie ein anderes verwenden, Zeichen (das Ausrufezeichen) an erweitern Umgebungsvariablen an Ausführungszeit. Wenn verzögerte Variable Expansion ermöglicht wird, die oberhalb Beispiele geschrieben werden könnte wie folgt zu arbeiten, wie beabsichtigt:
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%
Andere Tipps
setlocal EnableDelayedExpansion
den / v-Freigabe-Flag
Sieht aus wie die Lese- und Schreib verschiedene Scoping-Regeln verwenden.
Wenn Sie beseitigen diese Zeile
set MODE=FOOBAR
es wird erwartet funktionieren. So müssen Sie wahrscheinlich eine komplexe Reihe haben, wenn if / elses die Variablen bevölkert werden, wie Sie möchten.