Gibt es eine Möglichkeit, eine bedingte IF- oder IF-Anweisung in eine Windows-Batchdatei zu schreiben?
Beispielsweise:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Gibt es eine Möglichkeit, eine bedingte IF- oder IF-Anweisung in eine Windows-Batchdatei zu schreiben?
Beispielsweise:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Antworten:
Die zmbq-Lösung ist gut, kann jedoch nicht in allen Situationen verwendet werden, z. B. in einem Codeblock wie einer FOR DO (...) - Schleife.
Eine Alternative ist die Verwendung einer Indikatorvariablen. Initialisieren Sie es so, dass es nicht definiert ist, und definieren Sie es dann nur, wenn eine der ODER-Bedingungen erfüllt ist. Verwenden Sie dann IF DEFINED als letzten Test - Sie müssen keine verzögerte Erweiterung verwenden.
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
Sie könnten die ELSE IF-Logik hinzufügen, die arasmussen verwendet, weil sie möglicherweise etwas schneller ausgeführt wird, wenn die erste Bedingung erfüllt ist, aber ich kümmere mich nie darum.
Nachtrag - Dies ist eine doppelte Frage mit nahezu identischen Antworten auf die Verwendung eines ODER in einem WinXP-Batch-Skript mit IF-Anweisung
Letzter Nachtrag - Ich habe fast meine Lieblingstechnik vergessen, um zu testen, ob eine Variable zu einer Liste von Werten gehört, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird. Initialisieren Sie eine Testvariable, die eine begrenzte Liste akzeptabler Werte enthält, und testen Sie dann mithilfe von Suchen und Ersetzen, ob sich Ihre Variable in der Liste befindet. Dies ist sehr schnell und verwendet minimalen Code für eine beliebig lange Liste. Es erfordert eine verzögerte Erweiterung (oder den Trick CALL %% VAR %%). Auch der Test ist CASE INSENSITIVE.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)
Das Obige kann fehlschlagen, wenn VAR enthält =
, sodass der Test nicht narrensicher ist.
Wenn Sie den Test innerhalb eines Blocks durchführen, in dem eine verzögerte Erweiterung erforderlich ist, um auf den aktuellen Wert von VAR zuzugreifen, dann
for ... do (
set "TEST=;val1;val2;val3;val4;val5;"
for /f %%A in (";!VAR!;") do if "!TEST:%%A=!" neq "!TEST!" (echo true) else (echo false)
)
Abhängig von den erwarteten Werten in VAR sind möglicherweise FOR-Optionen wie "delims =" erforderlich
Die obige Strategie kann auch =
in VAR durch Hinzufügen von etwas mehr Code zuverlässig gemacht werden.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true
Jetzt haben wir jedoch die Möglichkeit verloren, eine ELSE-Klausel bereitzustellen, sofern wir keine Indikatorvariable hinzufügen. Der Code hat begonnen, ein bisschen "hässlich" auszusehen, aber ich denke, er ist die zuverlässigste Methode zum Testen, ob VAR eine beliebige Anzahl von Optionen ist, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird.
Schließlich gibt es eine einfachere Version, die meiner Meinung nach etwas langsamer ist, da für jeden Wert eine IF ausgeführt werden muss. Aacini hat diese Lösung in einem Kommentar zur akzeptierten Antwort im zuvor genannten Link bereitgestellt
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A echo true
Die Werteliste darf nicht das * oder? Enthalten. Zeichen und die Werte und %VAR%
sollte keine Anführungszeichen enthalten. Zitate führen zu Problemen , wenn die %VAR%
auch Leer- oder Sonderzeichen enthalten wie ^
, &
usw. Eine andere Einschränkung bei dieser Lösung ist es nicht die Möglichkeit , für eine ELSE - Klausel zur Verfügung stellen , wenn Sie eine Indikatorvariable hinzufügen. Vorteile sind, dass je nach Vorhandensein oder Fehlen einer IF- /I
Option zwischen Groß- und Kleinschreibung unterschieden werden kann .
Das glaube ich nicht. Verwenden Sie einfach zwei IFs und GOTO das gleiche Label:
IF cond1 GOTO foundit
IF cond2 GOTO foundit
ECHO Didn't found it
GOTO end
:foundit
ECHO Found it!
:end
ECHO Didn't find it
selbst wenn es es finden würde.
Danke für diesen Beitrag, er hat mir sehr geholfen.
Keine Ahnung, ob es helfen kann, aber ich hatte das Problem und dank Ihnen habe ich herausgefunden, was meiner Meinung nach ein anderer Weg ist, es basierend auf dieser booleschen Äquivalenz zu lösen:
"A oder B" ist dasselbe wie "nicht (nicht A und nicht B)"
So:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Wird:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
Ein einfaches "FOR" kann in einer einzelnen Zeile verwendet werden, um eine "oder" Bedingung zu verwenden:
FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}
Auf Ihren Fall angewendet:
FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
Auch wenn diese Frage etwas älter ist:
Wenn Sie verwenden möchten, if cond1 or cond 2
sollten Sie keine komplizierten Schleifen oder ähnliches verwenden.
Einfach beides ifs
nacheinander in Kombination mit goto
- das ist ein implizites oder.
//thats an implicit IF cond1 OR cond2 OR cond3
if cond1 GOTO doit
if cond2 GOTO doit
if cond3 GOTO doit
//thats our else.
GOTO end
:doit
echo "doing it"
:end
Ohne goto, aber eine "Inplace" -Aktion, können Sie die Aktion dreimal ausführen, wenn ALLE Bedingungen übereinstimmen.
Es gibt jedoch kein IF <arg> OR
oder ELIF
oder ELSE IF
in Batch ...
Versuchen Sie, die anderen IFs im ELSE der vorherigen IF zu verschachteln.
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
Es ist möglich, eine Funktion zu verwenden, die die ODER-Logik auswertet und einen einzelnen Wert zurückgibt.
@echo off
set var1=3
set var2=5
call :logic_or orResult "'%var1%'=='4'" "'%var2%'=='5'"
if %orResult%==1 (
echo At least one expression is true
) ELSE echo All expressions are false
exit /b
:logic_or <resultVar> expression1 [[expr2] ... expr-n]
SETLOCAL
set "logic_or.result=0"
set "logic_or.resultVar=%~1"
:logic_or_loop
if "%~2"=="" goto :logic_or_end
if %~2 set "logic_or.result=1"
SHIFT
goto :logic_or_loop
:logic_or_end
(
ENDLOCAL
set "%logic_or.resultVar%=%logic_or.result%"
exit /b
)
&& ... || ...
Syntax direkt anstelle der zusätzlichen IF ... ELSE ...
Anweisung verwenden.
Das Ziel kann durch indirekte Verwendung von IFs erreicht werden.
Im Folgenden finden Sie ein Beispiel für einen komplexen Ausdruck, der in einem CMD-Stapel ohne inkohärente Beschriftungen und GOTOs sehr präzise und logisch geschrieben werden kann.
Codeblöcke zwischen () Klammern werden von CMD als (pathetische) Art von Unterschale behandelt. Welcher Exit-Code aus einem Block kommt, wird verwendet, um den True / False-Wert zu bestimmen, den der Block in einem größeren booleschen Ausdruck spielt. Mit diesen Codeblöcken können beliebig große boolesche Ausdrücke erstellt werden.
Einfaches Beispiel
Jeder Block wird in true aufgelöst (dh ERRORLEVEL = 0, nachdem die letzte Anweisung im Block ausgeführt wurde) / false, bis der Wert des gesamten Ausdrucks bestimmt wurde oder die Steuerung herausspringt (z. B. über GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
Komplexes Beispiel
Dies löst das ursprünglich aufgeworfene Problem. In jedem Block sind mehrere Anweisungen möglich, jedoch im || || || Ausdruck Es ist vorzuziehen, präzise zu sein, damit es so lesbar wie möglich ist. ^ ist ein Escape-Zeichen in CMD-Stapeln. Wenn es am Ende einer Zeile platziert wird, wird es der EOL entkommen und CMD anweisen, den aktuellen Stapel von Anweisungen in der nächsten Zeile weiterzulesen.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(
(CALL :ProcedureType1 a b) ^
|| (CALL :ProcedureType2 sgd) ^
|| (CALL :ProcedureType1 c c)
) ^
&& (
ECHO -=BINGO=-
GOTO :EOF
)
ECHO -=no bingo for you=-
GOTO :EOF
:ProcedureType1
IF "%~1" == "%~2" (EXIT /B 0) ELSE (EXIT /B 1)
GOTO :EOF (this line is decorative as it's never reached)
:ProcedureType2
ECHO :ax:xa:xx:aa:|FINDSTR /I /L /C:":%~1:">nul
GOTO :EOF
If %x%==1 (
If %y%==1 (
:: both are equal to 1.
)
)
Hiermit wird überprüft, ob mehrere Variablen den gleichen Wert haben. Hier ist für jede Variable.
If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)
Ich habe nur von oben an das gedacht, wenn mein Kopf. Ich könnte es mehr verdichten.
Mir ist klar, dass diese Frage alt ist, aber ich wollte eine alternative Lösung veröffentlichen, falls jemand anderes (wie ich) diesen Thread gefunden hat, während er dieselbe Frage hat. Ich konnte das Fehlen eines OR-Operators umgehen, indem ich die Variable wiederholte und findstr zur Validierung verwendete.
for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
if %errorlevel% equ 0 echo true
)
Während die Antwort von dbenham ziemlich gut ist, IF DEFINED
kann das Verlassen auf Sie in große Schwierigkeiten geraten, wenn die Variable, die Sie überprüfen, keine Umgebungsvariable ist. Skriptvariablen erhalten diese spezielle Behandlung nicht.
Während dies wie eine lächerliche undokumentierte BS erscheinen mag, zeigt eine einfache Shell-Abfrage IF
mit IF /?
, dass
Die Bedingung DEFINED funktioniert genau wie EXIST, außer dass sie einen Umgebungsvariablennamen verwendet und true zurückgibt, wenn die Umgebungsvariable definiert ist.
Gibt es bei der Beantwortung dieser Frage einen Grund, nach einer Reihe von Bewertungen nicht einfach ein einfaches Flag zu verwenden? Dies scheint OR
mir die flexibelste Prüfung zu sein, sowohl hinsichtlich der zugrunde liegenden Logik als auch der Lesbarkeit. Beispielsweise:
Set Evaluated_True=false
IF %condition_1%==true (Set Evaluated_True=true)
IF %some_string%=="desired result" (Set Evaluated_True=true)
IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)
IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)
Natürlich können sie jede Art von bedingter Bewertung sein, aber ich teile nur einige Beispiele.
Wenn Sie alles schriftlich in einer Zeile haben möchten, können Sie sie einfach mit folgenden Elementen verketten &&
:
Set Evaluated_True=false
IF %condition_1%==true (Set Evaluated_True=true) && IF %some_string%=="desired result" (Set Evaluated_True=true) && IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)
IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)
Nie existiert, um zu arbeiten.
Ich benutze wenn nicht vorhanden g: xyz / was gehe zu h: Sonst xcopy c: aktuell / Dateien g: bu / aktuell Es gibt Modifikatoren / a usw. Ich bin mir nicht sicher, welche. Laptop im Laden. Und Computer im Büro. Ich bin nicht da.
Batch-Dateien funktionieren nie über Windows XP
Eine viel schnellere Alternative, die ich normalerweise verwende, ist die folgende, da ich eine beliebige Anzahl von Bedingungen "oder" kann, die in einen variablen Raum passen können
@(
Echo off
Set "_Match= 1 2 3 "
)
Set /a "var=3"
Echo:%_Match%|Find " %var% ">nul || (
REM Code for a false condition goes here
) && (
REM code for a true condition goes here.
)
Als mir klar wurde, dass dies eine alte Frage ist, haben mir die Antworten geholfen, eine Lösung zum Testen von Befehlszeilenargumenten für eine Batchdatei zu finden. Daher wollte ich meine Lösung auch veröffentlichen, falls jemand anderes nach einer ähnlichen Lösung suchte.
Als erstes sollte ich darauf hinweisen, dass ich Probleme hatte, IF ... ELSE-Anweisungen innerhalb einer FOR ... DO-Klausel zum Laufen zu bringen. Es stellt sich heraus (danke an dbenham, dass er in seinen Beispielen versehentlich darauf hingewiesen hat), dass die ELSE-Anweisung nicht in einer separaten Zeile von den schließenden Parens stehen darf.
Also stattdessen:
FOR ... DO (
IF ... (
)
ELSE (
)
)
Was meine Präferenz für Lesbarkeit und ästhetische Gründe ist, müssen Sie dies tun:
FOR ... DO (
IF ... (
) ELSE (
)
)
Jetzt wird die ELSE-Anweisung nicht als nicht erkannter Befehl zurückgegeben.
Schließlich habe ich Folgendes versucht: Ich wollte in der Lage sein, mehrere Argumente in beliebiger Reihenfolge an eine Batchdatei zu übergeben, Groß- und Kleinschreibung zu ignorieren und undefinierte Argumente zu melden / fehlzuschlagen. Hier ist meine Lösung ...
@ECHO OFF
SET ARG1=FALSE
SET ARG2=FALSE
SET ARG3=FALSE
SET ARG4=FALSE
SET ARGS=(arg1 Arg1 ARG1 arg2 Arg2 ARG2 arg3 Arg3 ARG3)
SET ARG=
FOR %%A IN (%*) DO (
SET TRUE=
FOR %%B in %ARGS% DO (
IF [%%A] == [%%B] SET TRUE=1
)
IF DEFINED TRUE (
SET %%A=TRUE
) ELSE (
SET ARG=%%A
GOTO UNDEFINED
)
)
ECHO %ARG1%
ECHO %ARG2%
ECHO %ARG3%
ECHO %ARG4%
GOTO END
:UNDEFINED
ECHO "%ARG%" is not an acceptable argument.
GOTO END
:END
Beachten Sie, dass dies nur über das erste fehlgeschlagene Argument berichtet. Wenn der Benutzer also mehr als ein inakzeptables Argument eingibt, wird er nur über das erste informiert, bis es korrigiert ist, dann über das zweite usw.
IF [%var%]==[1] IF [%var2%]==[2] ECHO BOTH ARE TRUE
. Ich habe immer definiertSET AND=IF
und dann geschrieben :IF cond1 %AND% cond2 ECHO BOTH ARE TRUE
.