Operatory logiczne („i”, „lub”) we wsadzie DOS

Odpowiedzi:

289

Możesz to zrobić andw warunkach zagnieżdżonych:

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

lub:

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

Możesz to zrobić orza pomocą oddzielnej zmiennej:

set res=F
if %hour% leq 6 set res=T
if %hour% geq 22 set res=T
if "%res%"=="T" (
    set state=asleep
)
paxdiablo
źródło
14
Można też po prostu użyć set res=lub set res=1, a następnie if defined res, który jest nieco bardziej odporne na literówki i działa nawet w blokach bez wyraźnego umożliwiający opóźnione ekspansji.
Joey,
5
Aby nieco poprawić swoją odpowiedź ... nie musisz jawnie zagnieżdżać instrukcji „jeśli” ... możesz je po prostu „połączyć”, jak pokazuje Dave Jarvis poniżej
JoelFan
Pamiętaj, aby nie zostawiać żadnych spacji po secie = true, albo rzecz po prostu z wdziękiem nie działa.
Zapisuje
1
Opisany przez ciebie warunek „lub” jest elegancki i działa świetnie dla zakresu liczb, ale co jeśli porównam 2 niezależne wartości, a nie zakres? Na przykład, jeśli ten plik istnieje lub nazwa pliku == ""
bakoyaro
1
@ bakoyaro, możesz użyć dowolnego warunku, aby ustawić res na true, w tym tych, o których wspominasz.
paxdiablo
69

IFOświadczenie nie obsługuje operatorów logicznych ( ANDi OR), kaskadowy IFoświadczenia zrobić niejawny koniunkcji.

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

Jeśli File1.Dat i File1.Dat istnieje, przeskocz etykietę FILE12_EXIST_LABEL.

Zobacz też: IF /?

Dave Jarvis
źródło
53

Prawa De Morgana pozwalają nam przekształcać rozłączenia („LUB”) w logiczne odpowiedniki, używając tylko spójników („ORAZ”) i negacji („NIE”). Oznacza to, że możemy połączyć rozłączenia („OR”) w jedną linię.

Oznacza to, że jeśli nazywa się „Yakko”, „Wakko” lub „Dot”, wówczas należy użyć echa „brat lub siostra Warner”.

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

Jest to kolejna wersja przykładu „LUB” paxdiablo, ale warunki są powiązane w jedną linię. (Zauważ, że przeciwieństwo leqjest gtr, a przeciwieństwo geqjest lss.)

set res=true
if %hour% gtr 6 if %hour% lss 22 set res=false
if "%res%"=="true" set state=asleep
anomalny
źródło
6

Poniższe przykłady pokazują, jak utworzyć instrukcję AND (używaną do ustawiania zmiennych lub włączania parametrów dla polecenia).

Aby uruchomić Notatnik i zamknąć okno CMD:

start notepad.exe & exit

Aby ustawić zmienne x, y i z na wartości, jeśli zmienna „a” jest równa bla.

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

Mam nadzieję, że to pomaga!

GinDiamond
źródło
5

OR jest nieco trudny, ale nie przesadnie. Oto przykład

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
Timo Salmi
źródło
2

Athul Prakash (wówczas 16 lat) dał logiczny pomysł, jak zaimplementować test OR, negując warunki w instrukcjach IF, a następnie używając klauzuli ELSE jako lokalizacji do umieszczenia kodu wymagającego wykonania. Pomyślałem sobie, że zwykle potrzebne są jednak jeszcze dwie klauzule, ponieważ sugeruje on użycie dwóch instrukcji IF, a zatem wykonany kod musi zostać napisany dwukrotnie . Jeśli jednak GOTO zostanie użyte do pominięcia wymaganego kodu, zamiast pisać klauzule ELSE, kod do wykonania musi zostać napisany tylko raz .

Oto sprawdzalny przykład tego, jak zaimplementowałbym negatywną logikę Athul Prakash, aby stworzyć OR .

W moim przykładzie ktoś może prowadzić czołg, jeśli ma licencję na czołg LUB LUB wykonuje swoją służbę wojskową . Wpisz true lub false po dwóch pytaniach, a będziesz mógł zobaczyć, czy logika pozwala prowadzić czołg.

@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
Ivan
źródło
2

Jeśli chcesz napisać znak if+ AND/ ORw jednej instrukcji, nie ma żadnej z nich. Ale nadal można grupa ifz &&/ ||a (/ )oświadczenia do osiągnięcia tego, co chcesz w jednej linii w / o dodatkowe zmienne i w / o if-elsepowielania bloku (pojedynczego echodowodzenia TRUEi FALSEsekcji Code):

@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

Wyjście :

TRUE+
FALSE-
FALSE-
FALSE-

TRUE+
TRUE+
TRUE+
FALSE-

Trik jest w typepoleceniu, które upuszcza / ustawia, errorlevela więc obsługuje drogę do następnego polecenia.

Andry
źródło
1

Spróbuj operand negacji - „nie”!

Cóż, jeśli możesz wykonać operację „ORAZ” na instrukcji if za pomocą zagnieżdżonej instrukcji „jeśli” (zapoznaj się z poprzednimi odpowiedziami), możesz zrobić to samo z operacją „jeśli nie”, aby wykonać operację „lub”.

Jeśli jeszcze nie masz pomysłu, czytaj dalej. W przeciwnym razie nie marnuj czasu i wróć do programowania.

Podobnie jak zagnieżdżone „jeśli są spełnione tylko wtedy, gdy wszystkie warunki są spełnione, tak samo zagnieżdżone”, jeśli nie są spełnione tylko wtedy, gdy wszystkie warunki są fałszywe. Jest to podobne do tego, co chcesz zrobić z operandem „lub”, prawda?

Nawet jeśli którykolwiek z warunków w zagnieżdżonym „jeśli nie” jest prawdziwy, całe stwierdzenie pozostaje niespełnione. Dlatego można użyć negacji „jeśli następują kolejno po sobie, pamiętając, że treść instrukcji warunku powinna być tym, co chcesz zrobić, jeśli wszystkie zagnieżdżone warunki są fałszywe. Ciało, które naprawdę chciałeś dać, powinno znaleźć się pod stwierdzeniem else.

A jeśli nadal nie dostałeś tego wszystkiego, przepraszam, mam 16 lat i to najlepsze, co mogę zrobić, aby to wyjaśnić.

Athul Prakash
źródło
x = 2 lub x = 3 =>! ! (x = 2 lub x = 3) =>! (x! = 2 i x! = 3) Nie sądzę, że można negować całość, jeśli struktura ma zastosować zewnętrzny operator „nie”. Minęły 3 lata, Athul-prakash, myśli?
Azeroth2b,
1

Jest to tak proste, jak następujące:

AND> if + if

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

LUB> 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*

Wiem, że istnieją inne odpowiedzi, ale myślę, że kopalnia jest prostsza, więc łatwiejsza do zrozumienia. Mam nadzieję, że to ci pomoże! ;)

Oprogramowanie Renk
źródło
0

Alternatywą jest poszukiwanie powłoki uniksowej, która daje operatorom logicznym i wiele więcej. Można uzyskać natywna implementacja win32 z Bourne shell tutaj jeśli nie chcesz iść cygwin trasą. Native bash można znaleźć tutaj . Jestem pewien, że możesz łatwo znaleźć w Google inne dobre alternatywy, takie jak zsh lub tcsh.

K.

Kevin Shea
źródło
4
Jeśli zamierzasz przejść przez wysiłek użycia innej powłoki, przynajmniej skorzystaj z PowerShell: microsoft.com/powershell
Eclipse
17
Istnieje wiele lepszych powłok niż DOS. Powodem, dla którego chciałbym użyć pliku bat DOS, jest to, że nie wymaga on żadnych zewnętrznych narzędzi. Jeśli masz klienta, który musi zautomatyzować coś prostego, czy naprawdę chcesz, aby instalował specjalne narzędzia (cygwin, perl, powershell itp.), Gdy wystarczy plik BAT?
Mark Lakata
3
BAT wystarcza przez większość czasu. 90% skryptów powłoki uniksowej napisanych przez ppl nie jest czystą powłoką, ale zawiera wiele wywołań coreutils, sed, awk itp. GNU zaimplementowało gadżety UNIX w innych systemach operacyjnych, w tym Windows. Więc spójrz na to getgnuwin32.sourceforge.net cmd.exe / bash / zsh, a to powinno wystarczyć na większość zadań. Nie ma powodu, aby uczyć się tak zwanego PowerShell, jeśli masz doświadczenie w zakresie BAT / UNIX Shell
MeaCulpa
0

Tylko część OR jest trudna, ale z ogólnym wyrażeniem logicznym zawierającym NIE LUB ORAZ jedynym fajnym rozwiązaniem jest:

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
Henrik4
źródło
-1

Niewielka modyfikacja odpowiedzi Andry'ego, zmniejszająca liczbę poleceń typu duplikat:

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
TedK
źródło