ตัวดำเนินการเชิงตรรกะ (“ และ”,“ หรือ”) ในชุด DOS


คำตอบ:


289

คุณสามารถทำได้andด้วยเงื่อนไขที่ซ้อนกัน:

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

หรือ:

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

คุณสามารถทำorกับตัวแปรแยก:

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

14
นอกจากนี้คุณยังสามารถใช้set res=หรือset res=1จากนั้นif defined resประสิทธิภาพของการพิมพ์ที่ผิดเพี้ยนไปกว่าเล็กน้อยและทำงานได้แม้ในบล็อกโดยไม่มีการเปิดใช้งานการขยายล่าช้า
Joey

5
เพียงเพื่อปรับปรุงคำตอบของคุณสักหน่อย ... คุณไม่จำเป็นต้องวางคำสั่ง "if" ไว้อย่างชัดเจน ... คุณสามารถ "
โยง

จงอย่าทิ้งช่องว่างใด ๆ หลังจาก set = true หรือสิ่งที่งดงามไม่สามารถใช้งานได้ มันจะเก็บค่า "จริง" ในตัวแปร ...
Roland Pihlakas

1
เงื่อนไข 'หรือ' ที่คุณอธิบายนั้นลื่นและทำงานได้ดีสำหรับช่วงของตัวเลข แต่ถ้าฉันเปรียบเทียบค่าอิสระ 2 ค่าและไม่ใช่ช่วง? ตัวอย่างเช่นหากไฟล์นี้มีอยู่หรือชื่อไฟล์ == ""
bakoyaro

1
@bakoyaro คุณสามารถใช้เงื่อนไขใด ๆ เพื่อตั้งค่า res เป็นจริงรวมถึงเงื่อนไขที่คุณพูดถึง
paxdiablo

69

IFคำสั่งไม่สนับสนุนการดำเนินการทางตรรกะ ( ANDและOR) ซ้อนIFงบทำการร่วมโดยปริยาย

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

ถ้าFile1.Dat และ มีอยู่แล้วกระโดดฉลากFile1.DatFILE12_EXIST_LABEL

ดูสิ่งนี้ด้วย: IF /?


53

กฎหมายของ De Morganอนุญาตให้เราแปลงความแตกต่าง ("OR") ให้เทียบเท่าเชิงตรรกะโดยใช้สันธาน ("AND") และ negations ("NOT") เท่านั้น ซึ่งหมายความว่าเราสามารถเชื่อมโยง ("OR") เข้ากับหนึ่งบรรทัด

ซึ่งหมายความว่าหากชื่อคือ "Yakko" หรือ "Wakko" หรือ "Dot" ให้เลือก "พี่ชายหรือน้องสาวของ 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

นี่เป็นอีกตัวอย่างหนึ่งของ "OR" ของ paxdiablo แต่เงื่อนไขถูกผูกมัดกับหนึ่งบรรทัด (โปรดทราบว่าสิ่งที่ตรงกันข้ามleqคือgtrและสิ่งที่ตรงกันข้ามgeqคือlss)

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

6

ตัวอย่างต่อไปนี้แสดงวิธีสร้างคำสั่ง AND (ใช้สำหรับตั้งค่าตัวแปรหรือรวมถึงพารามิเตอร์สำหรับคำสั่ง)

ในการเริ่มต้น Notepad และปิดหน้าต่าง CMD:

start notepad.exe & exit

ในการตั้งค่าตัวแปร x, y และ z เป็นค่าหากตัวแปร 'a' เท่ากับ blah

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

หวังว่าจะช่วย!


5

หรือมีเล่ห์เหลี่ยมเล็กน้อย แต่ไม่มากเกินไป นี่คือตัวอย่าง

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 (อายุ 16 ปีในขณะนั้น) ให้ความคิดเชิงตรรกะสำหรับวิธีการใช้การทดสอบ OR โดยปฏิเสธเงื่อนไขในคำสั่ง IF จากนั้นใช้คำสั่ง ELSE เป็นที่ตั้งเพื่อวางรหัสที่ต้องใช้การดำเนินการ ฉันคิดกับตัวเองว่ามี แต่สองข้ออื่นมักจะจำเป็นตั้งแต่เขาจะแนะนำการใช้สอง IF งบและเพื่อให้รหัสการดำเนินการจะต้องมีการเขียนเป็นครั้งที่สอง แต่ถ้า GOTO จะใช้ในการข้ามผ่านรหัสที่ต้องการแทนการเขียนคำสั่ง ELSE รหัสสำหรับการดำเนินการเพียงต้องการที่จะเขียนครั้งเดียว

นี่เป็นตัวอย่างที่ทดสอบได้ว่าฉันจะใช้ตรรกะเชิงลบของ Athul Prakash เพื่อสร้างORได้อย่างไร

ในตัวอย่างของฉันบางคนได้รับอนุญาตให้ขับรถถังถ้าพวกเขามีใบอนุญาตรถถังหรือพวกเขากำลังรับราชการทหารอยู่ ป้อนจริงหรือเท็จที่ข้อความแจ้งทั้งสองและคุณจะสามารถดูได้ว่าตรรกะอนุญาตให้คุณขับรถถังหรือไม่

@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

หากคุณมีความสนใจที่จะเขียนif+ AND/ ORในหนึ่งคำสั่งแล้วไม่มีคำสั่งใด ๆ แต่คุณยังสามารถจัดกลุ่มifด้วย&&/ ||และ(/ )statement เพื่อให้บรรลุตามที่คุณต้องการในหนึ่งบรรทัดโดยไม่มีตัวแปรเพิ่มเติมและการif-elseทำซ้ำบล็อกw / o ( echoคำสั่งเดียวสำหรับTRUEและFALSEส่วนของโค้ด):

@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

ผลผลิต :

TRUE+
FALSE-
FALSE-
FALSE-

TRUE+
TRUE+
TRUE+
FALSE-

เคล็ดลับอยู่ในtypeคำสั่งซึ่งดร็อป / เซ็ตerrorlevelและจัดการกับคำสั่งถัดไป


1

ลองใช้เนกาทีฟ - 'ไม่'!

ดีถ้าคุณสามารถดำเนินการ 'และ' ในคำสั่ง if โดยใช้ซ้อน 'if's (ดูคำตอบก่อนหน้า) แล้วคุณสามารถทำสิ่งเดียวกันกับ' ถ้าไม่ 'เพื่อดำเนินการ' หรือ '

หากคุณยังไม่เข้าใจแนวคิดนี้โปรดอ่านต่อ มิฉะนั้นอย่าเพิ่งเสียเวลาและกลับไปเขียนโปรแกรม

เช่นเดียวกับที่ซ้อนกัน 'หากมีความพึงพอใจก็ต่อเมื่อเงื่อนไขทั้งหมดเป็นจริงเท่านั้น' ที่ซ้อนกัน 'หากไม่พึงพอใจก็ต่อเมื่อเงื่อนไขทั้งหมดเป็นเท็จ สิ่งนี้คล้ายกับสิ่งที่คุณต้องการทำกับตัวถูกดำเนินการ 'หรือ' ใช่ไหม?

แม้ว่าจะมีเงื่อนไขใด ๆ ใน 'ที่ไม่อยู่' ที่ซ้อนกันเป็นจริง แต่ข้อความทั้งหมดยังคงไม่เป็นที่พอใจ ดังนั้นคุณสามารถใช้ negated 'if' อย่างต่อเนื่องโดยการจดจำว่าเนื้อความของเงื่อนไข statement ควรเป็นสิ่งที่คุณต้องการทำถ้าเงื่อนไขที่ซ้อนกันทั้งหมดของคุณเป็นเท็จ ร่างกายที่คุณต้องการให้จริงควรมาภายใต้คำสั่งอื่น

และถ้าคุณยังไม่เข้าใจสิ่งที่กล่าวมาขอโทษด้วยฉันอายุ 16 ปีและนั่นเป็นวิธีที่ดีที่สุดที่ฉันสามารถอธิบายได้


x = 2 หรือ x = 3 =>! ! (x = 2 หรือ x = 3) =>! (x! = 2 และ x! = 3) ฉันไม่คิดว่าคุณสามารถลบล้างทั้งหมดได้หากโครงสร้างเพื่อใช้ตัวดำเนินการ "ไม่" ด้านนอกที่จำเป็น เป็นเวลา 3 ปีแล้ว @ Athul-prakash ความคิด?
Azeroth2b

1

มันง่ายเหมือนดังต่อไปนี้:

และ> ถ้า + ถ้า

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

หรือ> ถ้า // ถ้า

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*

ฉันรู้ว่ามีคำตอบอื่น ๆ แต่ฉันคิดว่าเหมืองของฉันนั้นง่ายกว่าและเข้าใจได้ง่ายกว่า หวังว่านี่จะช่วยคุณได้! ;)


0

อีกทางเลือกหนึ่งคือการมองหายูนิกซ์เชลล์ที่ให้ตัวดำเนินการเชิงตรรกะแก่คุณและอีกมากมาย คุณสามารถรับการใช้งาน win32 แบบดั้งเดิมของเชลล์เป้าหมายได้ที่นี่หากคุณไม่ต้องการไปเส้นทาง cygwin ทุบตีพื้นเมืองสามารถพบได้ที่นี่ ฉันค่อนข้างแน่ใจว่าคุณสามารถ google ทางเลือกที่ดีอื่น ๆ ได้อย่างง่ายดายเช่น zsh หรือ tcsh

K


4
หากคุณจะต้องใช้ความพยายามในการใช้เปลือกที่แตกต่างกันอย่างน้อยก็ไปกับ PowerShell: microsoft.com/powershell
Eclipse

17
มีเชลล์ที่ดีกว่า DOS หลายตัว เหตุผลที่ฉันจะใช้ไฟล์ bat bat เป็นเพราะไม่ต้องใช้เครื่องมือภายนอก หากคุณมีลูกค้าที่ต้องการทำให้บางสิ่งง่าย ๆ คุณต้องการให้พวกเขาต้องติดตั้งเครื่องมือพิเศษ (cygwin, perl, powershell และอื่น ๆ ) เมื่อไฟล์ BAT พอเพียงหรือไม่?
Mark Lakata

3
BAT นั้นใช้เวลาส่วนใหญ่พอสมควร 90% ของ unix shell script ppl write ไม่ใช่ shell บริสุทธิ์ แต่มี coreutils, sed, awk และการโทรจำนวนมาก GNU ได้ใช้สารพัด UNIX ในระบบปฏิบัติการอื่นรวมถึง Windows ดังนั้นลองมาดูที่getgnuwin32.sourceforge.net cmd.exe / bash / zsh อันนี้น่าจะเพียงพอสำหรับงานส่วนใหญ่ ไม่มีเหตุผลที่จะเรียนรู้สิ่งที่เรียกว่า PowerShell หากคุณมีประสบการณ์ BAT / UNIX Shell
MeaCulpa

0

เฉพาะส่วนหรือเป็นเรื่องยุ่งยาก แต่ด้วยนิพจน์บูลีนทั่วไปที่มี NOT OR และทางออกที่ดีเพียงอย่างเดียวคือ:

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

ปรับเปลี่ยนเล็กน้อยเพื่อตอบของ Andry ลดคำสั่งประเภทที่ซ้ำกัน:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.