Warum ist die verzögerte Erweiterung in einer batch-Datei funktioniert nicht in diesem Fall?
Dieser code
@echo off
setlocal EnableDelayedExpansion
set myvar=first
set first=second
echo myvar:!myvar!
set myvar=!myvar!
echo myvar:!myvar!
gibt
myvar:first
myvar:first
unter Windows Vista SP2.
Die Ausgabe, die ich erwartet hatte ist
myvar:first
myvar:second
Warum der Unterschied und wie Sie die gewünschte Wirkung?
- Das problem ist, dass
set myvar=!myvar!
erweitert, umset myvar=first
legen Sie es mit dem gleichen Inhalt, und dann Fragen Sieecho myvar:!myvar!
den Inhalt von myvar - Gut, Sie sind völlig richtig. Wie könnte ich verpasst haben dies... Könnten Sie bitte geben Sie diese als Antwort (evtl. mit Zusatz von zusätzliche Informationen, die Sie nützlich finden)?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das problem ist, dass
set myvar=!myvar!
erweitert, umset myvar=first
,legen Sie es mit dem gleichen Inhalt, und dann Fragen Sie
echo myvar:!myvar!
den Inhalt von myvar.Werde ich versuchen, ein paar mehr Erklärungen, auch wenn Aacini und shf301 die Frage bereits beantwortet.
Beide zeigten den double-Erweiterung mit der
!%var%!
konstruieren, und Aacini erklärt, warum es funktionieren kann, und warum die umgekehrte version%!var!%
nicht arbeiten kann.IMHO gibt es vier verschiedene Erweiterungen.
Verzögerte Erweiterung:
Als Aacini erklärt die verzögerte Erweiterung ist sicher gegen jegliche Sonderzeichen im Inhalt (es kann mit ALLEN Zeichen von 0x01 bis 0xFF).
Prozent Expansion:
Die Prozent-Erweiterung nicht umgehen kann oder entfernt einige Zeichen (auch mit der Flucht).
Es kann nützlich sein, für einfache Inhalte, wie Sie erweitern können Variablen nach einem
endlocal
Barriere.FÜR-Loop-Parameter Erweiterung:
Es ist sicher, wenn die verzögerte Erweiterung deaktiviert ist, da sonst die verzögerte Erweiterung phase ausgeführt wird, nachdem der ausbau des %%a-Variablen.
Es kann sinnvoll sein, kann es zu erweitern, Variablen nach einem
endlocal
BarriereSET Erweiterung:
set var
erweitert auch eine variable, und es ist immer sicher und arbeitet unabhängig von der verzögerten expansion mode.Aacini gerade erklärt, wie die
call %%%var%%%
Konstrukt arbeiten, ich möchte nur einige zusätzliche Bemerkungen.call
ist stapelbar, Sie können viele von Ihnen, und jeder startet den parser.Ergebnisse zu
%var%######
Aber
call
haben viele Nachteile/Nebenwirkungen!Jeder Anruf doppelt alle carets
^
Sie können sagen: "Hey, ich habe es getestet, und ich kann nicht sehen, jeder Verdoppelung"
Ergebnis
^
Doch es ist wahr, aber es ist meist versteckt, da jeder Neustart haben auch einen speziellen Charakter phase, wo carets entweicht das nächste Zeichen, aber Sie können sehen, die Verdoppelung Effekt mit
Ergebnis
"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"^
Selbst wenn ein call-ausbau startet den parser, man kann nie verwenden Sie die verzögerte Erweiterung in jeder phase (nur der erste).
call
Stoppt, wenn es erkennt nicht korrekt codierten Sonderzeichen.Nur die ersten Ergebnisse an den Ausgang
you & me
alle anderen schlägt fehl.Ein weiteres problem ist, dass call ist extrem langsam, eine
call set var=content
ist ~50times langsamer alsset var=content
, die Ursache ist, dass call-versuchen, starten Sie ein externes Programm.Ich hoffe, es war interessant ein bisschen ...
Und wenn Sie möchten, gehen mehr in die Tiefe Lesen Sie RUFEN Sie mich an, oder besser, zu vermeiden, rufen Sie
und Wie funktioniert die Windows-Kommando-Interpreter (CMD.EXE) analysieren Skripts?
set myvar=first
set first=second
set second=third
call call set myvar=%%%%%%%myvar%%%%%%%
echo %myvar%
display:third
SET VAR
ist bequem, aber riskant. Wenn beide VAR und VAR2 sind definiert, dann SET VAR geben beide Definitionen. 2) ich glaube, Sie können fügen Sie eine 5. Ebene:SET /A
Erweiterung von Variablen ohne % or !, solange der Inhalt eine Zahl ist.Dieses problem bezieht sich nicht direkt auf die Verzögerte Erweiterung von Umgebungsvariablen, sondern um die Tatsache, dass die beiden Wert sind Erweiterungen erforderlich: in den ersten geben Sie den Namen der Variablen und muss die zweite ersetzen Sie diesen Namen durch seinen Wert. Der direkte Weg zu tun, ist durch zwei Erweiterungen in der gleichen Zeile wie in der vorherigen Antwort:
set myvar=!%myvar%!
das funktioniert, weil %var% ausbau abgeschlossen ist, bevor der Befehl-Linie analysiert, die für die Ausführung in der Erwägung, dass !var! ausbau erfolgt später, kurz bevor der Befehl ausgeführt wird (daher die "verspätete" Namen). Dies bedeutet, dass %var% ausbau bieten können, Teile des Befehls und verursachen Fehler in der syntax, aber !var! nicht. Zum Beispielif %var%==value ...
einen Fehler verursachen, wenn var leer ist oder Leerzeichen, aberif !var!==value ...
nie zu einem Syntaxfehler.Die doppelte expansion der Werte kann auf anderen wegen erreicht werden, die nicht die Verzögerte Erweiterung von Umgebungsvariablen. Zum Beispiel können wir eine zusätzliche Batch-Datei, die die zweite Erweiterung:
Vorherigen Methode kann verwendet werden, um einen Dritten oder noch tieferen Ebene Erweiterungen, und sogar kombiniert werden, die eine Verzögerte Erweiterungen zu erstellen sehr komplexer Wert-managements. Diese Sache ist nicht nur ein Kuriosum, aber der Schlüssel zum Zugriff auf array-Elemente oder verketteten Listen. Zum Beispiel:
call set myvar=%%%myvar%%%
call
schafft einen neuen Kontext (in der gleichen Zeile), wo die zweite expansion ist erreicht. Mit der Hilfs-Batch-Datei das ist ganz klar, aber dein Vorschlag ist besser, richtigen code schreiben. +1!call set...
. Könnten Sie das näher erläutern?call set myvar=%%%myvar%%%
ausgeführt wird, auf diese Weise: 1. Ersetzen Sie %% durch % und %myvar% von seinem Wert, der sich incall set myvar=%first%
2. Der CALL-Befehl ausgeführt wird, so führt er wiederum seinen Befehl, aber in einem neuen Kontext, wo es wieder aufbereitet, als wäre es gerade gelesen aus der Batch-Datei. 3. Dieset myvar=%first%
erfolgt in der üblichen Weise: ersetzen Sie die %ersten% durch den Wert (den zweiten) und weisen Sie ihn myvar:set myvar=second
.Was Sie zu tun versuchen, wird nicht funktionieren - verzögerte Erweiterung ändert sich nur die variable expansion Verhalten einer Variablen innerhalb eines Blocks. Gestattet es Ihnen nicht, die aliasing/Schachteln (aus Mangel eines besseren Wortes), dass Sie versuchen.
set myvar=first
wird die variable myvar auf den text "erste".set first=second
wird die variable zunächst den text "zweiter. Es gibt keine Verbindung zwischen diesen beiden Linien.myvar
nie bewerten, zu etwas, es war nicht ausdrücklich festgelegt.Glaube ich nicht, es ist jedenfalls zu erreichen, was Sie hier zu tun versuchen.
* Edit *
OK, nach der Einnahme eines Blick auf Ihre Antwort ich sehen, wie das funktioniert, können Sie sich Ihre gewünschte Ausgabe mit dabei:
Also die Magie scheint zu geschehen wegen der Art und Weise, standard und verzögert die expansion auftreten. Die Linie
set myvar=!%myvar%!
scheint erweitert werden zunächst von der standard-expanderset myvar=!first!
(Sie erkennen dies, wenn Sie das Skript ausführen, mitecho on
). Dann verzögert, expander betreibt und erweitert!first
zur "zweiten", und setzen Sie diemyvar
zu.Ich habe keine Ahnung, ob dies dokumentiert sich Verhalten, wie standard und verzögert die expansion arbeiten sollte oder nur ein detail (was bedeutet, dass es brechen könnte in der Zukunft)
myvar
nie bewerten, zu etwas, dass es nicht explizit auf. Es wird von " neuen Wert explizit in die Linieset myvar=!myvar!
. Siehe mein Antwort für den Vergleich.set %1=!var!
erweitert, umset myvar=!var!
(führen Sie es mit echo on), so ist es noch eindeutiger Satz in diesem Beispiel. BTW das ist ein cooles Beispiel, ich hatte nie die Idee Sie zu kombinieren, normale und verzögerte Erweiterung so.set myvar=!myvar!
aus dem Skript in dieser Frage und dieset myvar=!var!
(was Sie sagen, ist das Ergebnis%1=!var!
) von der anderen Frage? Ich dont sehen. Zu mir, Sie sollte das gleiche; die Rechte Seite wird ausgewertet und als Wert der Variablen bezeichnet, die von der linken Seite.!%var%!
in der anderen Frage ad !%myvar%! bewegen sich die Werte um.!
) ist die nur was sollte man in der Lage sein müssen zu Lesen frei geschachtelte Wert, oder?