Nehmen Sie diese einfache Reihe von Befehlen, die in einer Batchumgebung ausgeführt werden:
>set ar[0]=orange
>set ar[1]=apple
>set ar[2]=banana
>for %i in (0,1,2) do echo !ar[%i]!
Es gibt Folgendes aus:
>echo !ar[0]!
!ar[0]!
>!ar[1]!
!ar[1]!
>!ar[2]!
!ar[2]!
Es wird also offensichtlich nicht auf seine Werte erweitert. Wie würde ich das tun?
Antwort1
Quellen:
Phase 5InWie analysiert der Windows-Befehlsinterpreter (CMD.EXE) Skripts?
Verzögerte Erweiterung:Nur wenn die verzögerte Erweiterung eingeschaltet ist, befindet sich der Befehl nicht in einemeingeklammerter Block auf beiden Seiten eines Rohrsund der Befehl ist kein"nacktes" Batch-Skript(Skriptname ohne Klammern, CALL, Befehlsverkettung oder Pipe).
- Jedes Token für einen Befehl wird unabhängig auf verzögerte Erweiterung analysiert.
- Die meisten Befehle analysieren zwei oder mehr Token – das Befehlstoken, das Argumenttoken und jedes Umleitungszieltoken.
- Der FOR-Befehl analysiert nur das Token der IN-Klausel.
- Der IF-Befehl analysiert nur die Vergleichswerte – entweder einen oder zwei, abhängig vom Vergleichsoperator.
- Überprüfen Sie für jedes analysierte Token zunächst, ob es ein enthält
!
. Wenn nicht, wird das Token nicht analysiert – wichtig für^
Zeichen. Wenn das Token ein enthält!
, scannen Sie jedes Zeichen von links nach rechts:- Handelt es sich um ein Caretzeichen (
^
), hat das nächste Zeichen keine besondere Bedeutung, das Caretzeichen selbst wird entfernt - Wenn es ein Ausrufezeichen ist, suchen Sie nach dem nächsten Ausrufezeichen (Caretzeichen werden nicht mehr beachtet) und erweitern Sie es auf den Wert der Variablen.
- Aufeinanderfolgende Öffnungen
!
werden zu einer einzigen zusammengefasst!
- Alle verbleibenden
!
ungepaarten
- Aufeinanderfolgende Öffnungen
- Das Erweitern von Variablen in dieser Phase ist „sicher“, da Sonderzeichen nicht mehr erkannt werden (auch nicht
<CR>
oder<LF>
). - Für eine ausführlichere Erklärung lesen Sie die 2. Hälfte von dbenham gleicher Thread - Ausrufezeichenphase
- Handelt es sich um ein Caretzeichen (
Phase 5.3) Rohrbearbeitung:Nur wenn sich Befehle auf beiden Seiten einer Pipe befinden.
Jede Seite der Pipe wird unabhängig und asynchron verarbeitet.
- Wenn der Befehl intern in cmd.exe ist oder es sich um eine Batchdatei handelt oder wenn es sich um einen in Klammern gesetzten Befehlsblock handelt, wird er in einem neuen cmd.exe-Thread über ausgeführt
%comspec% /S /D /c" commandBlock"
, sodass der Befehlsblock einen Phasenneustart erhält, dieses Mal jedoch im Befehlszeilenmodus.- Wenn es sich um einen eingeklammerten Befehlsblock handelt,
<LF>
werden alle mit einem Befehl davor und danach in umgewandelt<space>&
. Die anderen<LF>
werden entfernt.
- Wenn es sich um einen eingeklammerten Befehlsblock handelt,
- Dies ist das Ende der Verarbeitung der Pipe-Befehle.
- Sehenhttps://stackoverflow.com/q/8192318/1012053für mehr Informationen zur Pipe-Analyse und -Verarbeitung
Phase 5.5) Umleitung ausführen:Alle in Phase 2 erkannten Umleitungen werden jetzt ausgeführt.
- Die Ergebnisse der Phasen 4 und 5 können Auswirkungen auf die in Phase 2 festgestellte Umleitung haben.
- Wenn die Umleitung fehlschlägt, wird der Rest des Befehls abgebrochen.Beachten Sie, dass eine fehlgeschlagene Umleitung ERRORLEVEL nicht auf 1 setzt, es sei denn,
||
es wird verwendet.
- Sie können auch die
Delayed Expansion
voncmd.exe
mit Flagge[/v:on | /v]
, auf derBefehlszeileoder imSchläger/cmdDateien.
- In deinemBefehlszeilemit
cmd.exe /v:on /c
set ar[0]=orange
set ar[1]=apple
set ar[2]=banana
for %i in (0,1,2) do cmd.exe /v:on /C"echo !ar[%i]!
- In deinemSchläger/cmdDatei ohne Angabe
setlocal enabledelayedexpansion
können Sie auchcmd.exe /v:on /c "command & command | command || command..."
@echo off
set "ar[0]=orange"
set "ar[1]=apple"
set "ar[2]=banana"
for %%i in (0,1,2)do cmd /v /c "echo\ !ar[%%i]!"
@echo off
set "ar[0]=orange"
set "ar[1]=apple"
set "ar[2]=banana"
setlocal enabledelayedexpansion
for %%i in (0,1,2)do echo\ !ar[%%i]!
enndlocal
@echo off
set "ar[0]=orange" & set "ar[1]=apple" & set "ar[2]=banana"
for %%i in (0,1,2)do %ComSpec% /v:on /c"echo !ar[%%i]!"
%__APPDIR__%timeout.exe /t -1 & endlocal & goto :EOF
@echo off
set "ar[0]=orange" & set "ar[1]=apple" & set "ar[2]=banana"
setlocal enabledelayedexpansion && for %%i in (0,1,2)do echo\ !ar[%%i]!
%__APPDIR__%timeout.exe /t -1 & endlocal & goto :EOF
@echo off
set "ar[0]=orange" && set "ar[1]=apple" && set "ar[2]=banana"
for %%i in (0,1,2)do <con: %ComSpec% /v:on /c"echo !ar[%%i]!"
call <con: rem./ && %__APPDIR__%timeout.exe /t -1 && endlocal
set "ar[0]=orange"
set "ar[1]=apple"
set "ar[2]=banana"
for %i in (0,1,2)do for %i in (0,1,2)do <con: call echo %ar[%i]%
- In deinemSchläger/cmdDatei oder Befehlszeile, alle folgenden Befehle sind gleich, wobei das Ersetzen zu beachten ist
%i
mit%%i
bei Verwendung inSchläger/cmdDateien
for %i in (0,1,2) do %ComSpec% /v:on /r "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec% /v:on /c "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe /v:on /r "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe /v:on /c "echo !ar[%i]!"
for %i in (0,1,2) do cmd /v:on /r "echo !ar[%i]!"
for %i in (0,1,2) do cmd /v:on /c "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec% /v /r "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec% /v /c "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe /v /r "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe /v /c "echo !ar[%i]!"
for %i in (0,1,2) do cmd /v /r "echo !ar[%i]!"
for %i in (0,1,2) do cmd /v /c "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v:on/r "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v:on/c "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v:on/r "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v:on/c "echo !ar[%i]!"
for %i in (0,1,2) do cmd/v:on/r "echo !ar[%i]!"
for %i in (0,1,2) do cmd/v:on/c "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v/r "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v/c "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v/r "echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v/c "echo !ar[%i]!"
for %i in (0,1,2) do cmd/v/r "echo !ar[%i]!"
for %i in (0,1,2) do cmd/v/c "echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v:on/r"echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v:on/c"echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v:on/r"echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v:on/c"echo !ar[%i]!"
for %i in (0,1,2) do cmd/v:on/r"echo !ar[%i]!"
for %i in (0,1,2) do cmd/v:on/c"echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v/r"echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v/c"echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v/r"echo !ar[%i]!"
for %i in (0,1,2) do cmd.exe/v/c"echo !ar[%i]!"
for %i in (0,1,2) do cmd/v/r"echo !ar[%i]!"
for %i in (0,1,2) do cmd/v/c"echo !ar[%i]!"
for %i in (0,1,2) do %ComSpec%/v/recho !ar[%i]!
for %i in (0,1,2) do %ComSpec%/v/cecho !ar[%i]!
for %i in (0,1,2) do cmd.exe/v/r"echo !ar[%i]!
for %i in (0,1,2) do cmd.exe/v/c"echo !ar[%i]!
for %i in (0,1,2) do cmd/v/recho !ar[%i]!
for %i in (0,1,2) do cmd/v/cecho !ar[%i]!
Weiterführende Literatur:
[√]Satz /?
[√]CMD /?
[√]For-Schleife
[√]Bedingte Ausführung || && ...
[√]Warum funktioniert der Call-Set anders?
[√]Grundlegendes zu Start, 2>nul, cmd und anderen Symbolen in einer Batchdatei
[√]Verwenden Sie Klammern/Klammern, um Ausdrücke in einer Windows-Batchdatei zu gruppieren
Antwort2
Die verzögerte Erweiterung wird hauptsächlich verwendet, um Variablenwerte mehr als einmal zu erweitern, insbesondere in For-Schleifen.
Zitat aushttps://ss64.com/nt/delayedexpansion.html
Die verzögerte Erweiterung führt dazu, dass Variablen in einer Batchdatei zum Ausführungszeitpunkt und nicht zum Analysezeitpunkt erweitert werden. Diese Option wird mit dem Befehl SETLOCAL EnableDelayedExpansion aktiviert.
Variablenerweiterung bedeutet das Ersetzen einer Variable (z. B. %windir%) durch ihren Wert C:\WINDOWS
Standardmäßig wird die Erweiterung nur einmal durchgeführt, und zwar vor der Ausführung jeder Zeile. Die !delayed!-Erweiterung wird bei jeder Ausführung der Zeile oder bei jeder Schleife in einem FOR-Schleifenbefehl durchgeführt. Sehen wir uns zunächst dieses Beispiel an:
set i=0
for /l %%a in (0,1,10) do (
set /a i=%i%+1
echo %i%
)
Hier erwarten wir, dass die Zahlen 1 bis 10 ausgegeben werden. Es wird jedoch jedes Mal nur 0 ausgegeben. Da die Variablen jedes Mal einmal erweitert werden, ändern sich die Werte nicht.
Dieses Mal versuchen wir es mit verzögerter Erweiterung:
setlocal enabledelayedexpansion
set i=0
for /l %%a in (0,1,10) do (
set /a i=!i!+1
echo !i!
)
Dieses Mal erhalten wir die erwartete Ausgabe, da sich der Wert jedes Mal ändert, wenn wir die Werte erweitern.
Ihr Code funktioniert nicht, weil Sie setlocal enabledelayedexpansion
am Anfang Ihres Codes hinzufügen müssen.
Ich hoffe, das hilft