Verwirrt über goto label (batch-Datei) Windows

Verwirrt über goto label (batch-Datei) Windows

Wenn ich diese Befehle auf diese Weise verwende, passiert das, was es soll:

Wennfoo Warzuvor als das eine oder andere festgelegt wurde, springt es zufoobar_menu

Wenn foozuvornichtals (dasselbe) eine Sache oder eine andere gesetzt ist, springt es zuanother_menu

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu

rem Check if foo was NOT previously set as bar1 or bar2...
if not "%foo%"=="bar1" goto :another_menu
if not "%foo%"=="bar2" goto :another_menu

Aus folgendem Grund ist es für mich verwirrend: Wenn ich diese wie unten gezeigt vertausche, funktioniert es nicht richtig und es geht an das falsche Etikett, aber warum?

rem Check if foo was NOT previously set as bar1 or bar2...
if not "%foo%"=="bar1" goto :another_menu
if not "%foo%"=="bar2" goto :another_menu

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu

Warum bewirken diese beiden Dinge nicht dasselbe?

Liegt das daran, dass ich die Goto-Teile nicht in Klammern setze?

Bei mir funktioniert es (auf die erste Art), aber das ist nicht die gleiche Reihenfolge wie bei meinen Menüs und ich wollte einfach, dass alles so läuft, wie es im zweiten (nicht funktionierenden) Beispiel oben dargestellt ist.

Prost.

BEARBEITEN:

Dies sind die eigentlichen Befehle. Wenn man sie so einstellt, wird, obwohl verschachtelt, trotzdem das Label aufgerufen, choose_audio_sample_rateauch wenn unter der Variable opus oder libopus eingestellt ist.

if not "%audio_codec%"=="libopus" if not "%audio_codec%"=="opus" goto :choose_audio_sample_rate
if "%audio_codec%"=="libopus" if "%audio_codec%"=="opus" goto :choose_audio_sample_rate_opus

Tatsächlich funktioniert die getauschte Variante auch nicht, sie geht auch, choose_audio_sample_rateobwohl unter der Variable opus oder libopus eingestellt ist.

if "%audio_codec%"=="libopus" if "%audio_codec%"=="opus" goto :choose_audio_sample_rate_opus
if not "%audio_codec%"=="libopus" if not "%audio_codec%"=="opus" goto :choose_audio_sample_rate

Ich verliere hier langsam den Verstand, lol, aber ok, es wird funktionieren (und direkt zum Nicht-Opus-Menü weiterleiten), wenn ich nur Folgendes verwende:

if "%audio_codec%"=="libopus" (goto :choose_audio_sample_rate_opus)
if "%audio_codec%"=="opus" (goto :choose_audio_sample_rate_opus)

Wenn es Libopus ist, geht es zum richtigen Label. Wenn es nicht Libopus ist, wird die nächste Zeile verarbeitet und wenn es Opus ist, geht es zum richtigen Label.

Wenn es darüber hinausging, war weder Libopus noch Opus erfolgreich und es ging weiter zum allgemeinen Menü.

Antwort1

Ihre Batchdatei wird von oben nach unten ausgeführt.

Im zweiten Beispiel wird immer zu gewechselt , auch wenn foo2oder gesetzt ist . Die Batchdatei kann diese beiden Anweisungen nur dann überspringen, wenn sowohl als auch gesetzt sind.foo1:another_menufoo1foo2

Sie schaffen im Wesentlichen eine logische Oder-Situation.

Wenn foo1 oder foo2 nicht gesetzt ist, gehe zu another_menu

ANDERS

Wenn foo1 ODER foo2 gesetzt ist, gehe zu foobar_menu

ANDERS

Nichts tun

Während das erste Beispiel

Wenn foo1 ODER foo2 gesetzt ist, gehe zu foobar_menu

ANDERS

Wenn foo1 oder foo2 nicht gesetzt ist, gehe zu another_menu

ANDERS

Nichts tun

Was Sie brauchen, ist insbesondere ein logisches UND. IF-Anweisungen in Batchdateien unterstützen weder UND noch ODER. Daher verschachteln oder verketten wir sie wie folgt:

if not "%foo1%"=="bar1" if not "%foo2%"=="bar2" goto :another_menu

Dies bedeutet: Wenn foo1 nicht gesetzt ist, dann gehe zu :another_menu, wenn foo2 nicht gesetzt ist

Oder einfacher: Wenn foo1 und foo2 nicht gesetzt sind, gehe zu another_menu

Antwort2

Ihre Logik kann durch die Verwendung von findstr etwas vereinfacht werden

 Echo("%foo%"|Findstr /C:"bar1" /C:"bar2" > nul && Goto :FooBarMenu || Goto :AnotherMenu

Die Logik: Findstr vergleicht den String %foo%mit bar1 und bar2. Wenn eine Übereinstimmung vorliegt, wird der Befehl erfolgreich abgeschlossen und der bedingte Operator &&führt den folgenden Befehl aus. Wenn keine Übereinstimmung vorliegt, ||wird der bedingte Operator ausgelöst und führt den folgenden Befehl aus, da der vorherige Befehl nicht erfolgreich ausgeführt wurde.

Beispiel:

@Echo off
 Set "foo=notbar"

:loop
 Echo("%foo%"|Findstr /C:"bar1" /C:"bar2" > nul ^
 && Call :fooBarMenu foobarMenu || Call :AnotherMenu Anothermenu
 If not defined foo Exit /B 0
Goto :loop

:foobarmenu
 Echo(@ %~1 foo = %foo%
 Set "foo="
Exit /B 0

:Anothermenu
 Echo(@ %~1 foo = %foo%
 Set "foo=bar2"
Exit /B 0

Antwort3

Sie haben bereits nach bar1und gesucht bar2. Sie müssen also nicht erneut prüfen, ob dies NICHT der Fall ist bar1oder bar2(es ist definitiv nicht der Fall, wenn der Codefluss diesen Punkt erreicht, da Sie bereits zu diesem Zeitpunkt woanders verzweigt sind).

rem Check if foo was previously set as bar1 or bar2...
if "%foo%"=="bar1" goto :foobar_menu
if "%foo%"=="bar2" goto :foobar_menu
rem no need to check if foo was NOT previously set as bar1 or bar2
rem if FOO is anything other than the previously checked values, 
rem your code will continue here anyway.
echo FOO isn't bar1 or bar2.
rem Don't forget to end this branch of your code or it will just continue to run:
goto :eof
:foobar_menu
echo reached foobar.

Sie können den /iSchalter mit verwenden if, um die Groß- und Kleinschreibung zu ignorieren
( if "foo"=="FOO"ist falsch, if /i "foo"=="FOO"ist wahr)

verwandte Informationen