Logische Operatoren ("und", "oder") im DOS-Stapel


Antworten:


289

Sie können andmit verschachtelten Bedingungen tun :

if %age% geq 2 (
    if %age% leq 12 (
        set class=child
    )
)

oder:

if %age% geq 2 if %age% leq 12 set class=child

Sie können ormit einer separaten Variablen arbeiten:

set res=F
if %hour% leq 6 set res=T
if %hour% geq 22 set res=T
if "%res%"=="T" (
    set state=asleep
)

14
Sie können auch einfach set res=oder set res=1und dann verwenden, if defined reswas etwas robuster gegen Tippfehler ist und sogar in Blöcken funktioniert, ohne die verzögerte Erweiterung explizit zu aktivieren.
Joey

5
Nur um Ihre Antwort ein wenig zu verbessern ... Sie müssen die "if"
-Anweisungen

Achten Sie darauf, keine Leerzeichen nach dem set = true zu lassen, oder das Ding funktioniert einfach nicht anmutig. Es würde den Wert "true" in der Variablen speichern ...
Roland Pihlakas

1
Die von Ihnen beschriebene 'oder'-Bedingung ist glatt und funktioniert hervorragend für einen Bereich von Zahlen. Was ist jedoch, wenn ich zwei unabhängige Werte vergleiche und keinen Bereich? Zum Beispiel, wenn diese Datei existiert oder Dateiname == ""
Bakoyaro

1
@bakoyaro, Sie können jede Bedingung verwenden, um res auf true zu setzen, einschließlich der von Ihnen erwähnten.
Paxdiablo

69

Die IFAnweisung unterstützt keine logischen Operatoren ( ANDund OR), kaskadierende IFAnweisungen bilden eine implizite Konjunktion.

IF Exist File1.Dat IF Exist File2.Dat GOTO FILE12_EXIST_LABEL

Wenn File1.Dat und File1.Dat vorhanden, dann überspringen Sie das Etikett FILE12_EXIST_LABEL.

Siehe auch: IF /?


53

De Morgans Gesetze erlauben es uns, Disjunktionen ("ODER") in logische Äquivalente umzuwandeln, indem wir nur Konjunktionen ("UND") und Negationen ("NICHT") verwenden. Dies bedeutet, dass wir Disjunktionen ("ODER") in einer Zeile verketten können.

Dies bedeutet, wenn der Name "Yakko" oder "Wakko" oder "Dot" ist, dann geben Sie "Warner Bruder oder Schwester" wieder.

set warner=true
if not "%name%"=="Yakko" if not "%name%"=="Wakko" if not "%name%"=="Dot" set warner=false
if "%warner%"=="true" echo Warner brother or sister

Dies ist eine andere Version von paxdiablos "ODER" -Beispiel, aber die Bedingungen sind an eine Zeile gekettet. (Beachten Sie, dass das Gegenteil von leqist gtrund das Gegenteil von geqist lss.)

set res=true
if %hour% gtr 6 if %hour% lss 22 set res=false
if "%res%"=="true" set state=asleep

6

Die folgenden Beispiele zeigen, wie eine AND-Anweisung erstellt wird (zum Festlegen von Variablen oder zum Einschließen von Parametern für einen Befehl).

So starten Sie Notepad und schließen das CMD-Fenster:

start notepad.exe & exit

Um die Variablen x, y und z auf Werte zu setzen, wenn die Variable 'a' gleich bla ist.

IF "%a%"=="blah" (set x=1) & (set y=2) & (set z=3)

Hoffentlich hilft das!


5

ODER ist etwas knifflig, aber nicht übermäßig. Hier ist ein Beispiel

set var1=%~1
set var2=%~2
::
set or_=
if "%var1%"=="Stack" set or_=true
if "%var2%"=="Overflow" set or_=true
if defined or_ echo Stack OR Overflow

2

Athul Prakash (damals 16 Jahre alt) gab eine logische Idee für die Implementierung eines ODER-Tests, indem er die Bedingungen in IF-Anweisungen negierte und dann die ELSE-Klausel als Speicherort für den Code verwendete, der ausgeführt werden muss. Ich dachte mir, dass es normalerweise zwei andere Klauseln gibt, die normalerweise benötigt werden, da er vorschlägt, zwei IF-Anweisungen zu verwenden, und daher muss der ausgeführte Code zweimal geschrieben werden . Wenn jedoch ein GOTO verwendet wird, um den erforderlichen Code zu überspringen, muss der Code für die Ausführung anstelle von ELSE-Klauseln nur einmal geschrieben werden .

Hier ist ein testbares Beispiel dafür, wie ich die negative Logik von Athul Prakash implementieren würde, um einen OP zu erstellen .

In meinem Beispiel darf jemand einen Panzer fahren, wenn er einen Panzerschein hat oder seinen Militärdienst leistet . Geben Sie bei den beiden Eingabeaufforderungen true oder false ein, und Sie können sehen, ob Sie mit der Logik einen Panzer fahren können.

@ECHO OFF
@SET /p tanklicence=tanklicence:
@SET /p militaryservice=militaryservice:

IF /I NOT %tanklicence%==true IF /I NOT %militaryservice%==true GOTO done

ECHO I am driving a tank with tanklicence set to %tanklicence% and militaryservice set to %militaryservice%

:done

PAUSE

2

Wenn Sie daran interessiert sind, ein if+ AND/ ORin eine Anweisung zu schreiben , gibt es keine davon. Sie können jedoch weiterhin ifmit &&/ ||und (/ )Anweisungen gruppieren , um das gewünschte Ergebnis in einer Zeile ohne zusätzliche Variablen und ohne if-elseBlockduplizierung (einzeln) zu erzielenecho Befehl für TRUEund FALSECodeabschnitte):

@echo off

setlocal

set "A=1" & set "B=2" & call :IF_AND
set "A=1" & set "B=3" & call :IF_AND
set "A=2" & set "B=2" & call :IF_AND
set "A=2" & set "B=3" & call :IF_AND

echo.

set "A=1" & set "B=2" & call :IF_OR
set "A=1" & set "B=3" & call :IF_OR
set "A=2" & set "B=2" & call :IF_OR
set "A=2" & set "B=3" & call :IF_OR

exit /b 0

:IF_OR
( ( if %A% EQU 1 ( type nul>nul ) else type 2>nul ) || ( if %B% EQU 2 ( type nul>nul ) else type 2>nul ) || ( echo.FALSE-& type 2>nul ) ) && echo TRUE+

exit /b 0

:IF_AND
( ( if %A% EQU 1 ( type nul>nul ) else type 2>nul ) && ( if %B% EQU 2 ( type nul>nul ) else type 2>nul ) && echo.TRUE+ ) || echo.FALSE-


exit /b 0

Ausgabe :

TRUE+
FALSE-
FALSE-
FALSE-

TRUE+
TRUE+
TRUE+
FALSE-

Der Trick liegt in dem typeBefehl, der das löscht / setzt errorlevelund so den Weg zum nächsten Befehl handhabt.


1

Versuchen Sie den Negationsoperanden - 'nicht'!

Wenn Sie eine 'AND'-Operation für eine if-Anweisung mit verschachtelten' if's ausführen können (siehe vorherige Antworten), können Sie dasselbe mit 'if not' tun, um eine 'or'-Operation auszuführen.

Wenn Sie die Idee noch nicht ganz haben, lesen Sie weiter. Ansonsten verschwenden Sie einfach keine Zeit und kehren Sie zur Programmierung zurück.

Genauso wie verschachtelte "wenn" nur erfüllt sind, wenn alle Bedingungen erfüllt sind, verschachtelte "wenn nicht" nur erfüllt sind, wenn alle Bedingungen falsch sind. Dies ähnelt dem, was Sie mit einem 'oder' Operanden machen möchten, nicht wahr?

Selbst wenn eine der Bedingungen im verschachtelten "Wenn nicht" zutrifft, bleibt die gesamte Aussage nicht erfüllt. Daher können Sie nacheinander negierte Ifs verwenden, indem Sie sich daran erinnern, dass der Hauptteil der Bedingungsanweisung das sein sollte, was Sie tun möchten, wenn alle Ihre verschachtelten Bedingungen falsch sind. Der Körper, den Sie tatsächlich geben wollten, sollte unter die else-Anweisung fallen.

Und wenn Sie immer noch nicht verstanden haben, tut mir leid, ich bin 16 und das ist das Beste, was ich tun kann, um es zu erklären.


x = 2 oder x = 3 =>! ! (x = 2 oder x = 3) =>! (x! = 2 und x! = 3) Ich glaube nicht, dass Sie die gesamte if-Struktur negieren können, um den erforderlichen äußeren "nicht" -Operator anzuwenden. Es ist 3 Jahre her, @ Athul-prakash, Gedanken?
Azeroth2b

1

Es ist genauso einfach wie das Folgende:

UND> wenn + wenn

if "%VAR1%"=="VALUE" if "%VAR2%"=="VALUE" *do something*

ODER> if // if

set BOTH=0
if "%VAR1%"=="VALUE" if "%VAR2%"=="VALUE" set BOTH=1
if "%BOTH%"=="0" if "%VAR1%"=="VALUE" *do something*
if "%BOTH%"=="0" if "%VAR2%"=="VALUE" *do something*

Ich weiß, dass es andere Antworten gibt, aber ich denke, dass die Mine einfacher und leichter zu verstehen ist. Hoffe das hilft dir! ;)


0

Eine Alternative besteht darin, nach einer Unix-Shell zu suchen, die Ihnen logische Operatoren und vieles mehr bietet. Sie können hier eine native win32-Implementierung einer Bourne-Shell erhalten , wenn Sie nicht auf die Cygwin-Route gehen möchten. Eine native Bash finden Sie hier . Ich bin mir ziemlich sicher, dass Sie andere gute Alternativen wie zsh oder tcsh leicht googeln können.

K.


4
Wenn Sie sich die Mühe machen möchten, eine andere Shell zu verwenden, sollten Sie zumindest PowerShell verwenden: microsoft.com/powershell
Eclipse

17
Es gibt viele bessere Shells als DOS. Der Grund, warum ich eine DOS-Bat-Datei verwenden würde, ist, dass keine externen Tools erforderlich sind. Wenn Sie einen Kunden haben, der etwas Einfaches automatisieren muss, möchten Sie wirklich, dass er spezielle Tools (Cygwin, Perl, Powershell usw.) installieren muss, wenn eine BAT-Datei ausreicht?
Mark Lakata

3
BAT ist die meiste Zeit genug. 90% der Unix-Shell-Skripte, die ppl write verwendet, sind keine reine Shell, sondern enthalten viele Aufrufe von coreutils, sed, awk usw. GNU hat UNIX-Goodies in anderen Betriebssystemen, einschließlich Windows, implementiert. Schauen Sie sich also diese getgnuwin32.sourceforge.net cmd.exe / bash / zsh an und dies sollte für die meisten Aufgaben ausreichen. Kein Grund, sogenannte PowerShell zu lernen, wenn Sie Erfahrung mit BAT / UNIX Shell haben
MeaCulpa

0

Nur der OR-Teil ist schwierig, aber mit einem allgemeinen booleschen Ausdruck, der NOT OR AND enthält, ist die einzige nette Lösung folgende:

REM if A == B OR C == C then yes

(call :strequ A B || call :strequ C C) && echo yes
exit /b

:strequ
if "%1" == "%2" exit /b 0
exit /b 1

-1

Leichte Änderung an Andrys Antwort, wodurch doppelte Typbefehle reduziert werden:

set "A=1" & set "B=2" & call :IF_AND
set "A=1" & set "B=3" & call :IF_AND
set "A=2" & set "B=2" & call :IF_AND
set "A=2" & set "B=3" & call :IF_AND

echo.

set "A=1" & set "B=2" & call :IF_OR
set "A=1" & set "B=3" & call :IF_OR
set "A=2" & set "B=2" & call :IF_OR
set "A=2" & set "B=3" & call :IF_OR

goto :eof

:IF_OR

(if /i not %A% EQU 1 (
   if /i not %B% EQU 2 (
      echo FALSE-
      type 2>nul
   )
)) && echo TRUE+

goto :eof

:IF_AND


(if /i %A% EQU 1 (
   if /i %B% EQU 2 (
      echo TRUE+
      type 2>nul
   )
)) && echo FALSE-

goto :eof
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.