Логічні оператори ("і", "або") в пакеті 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
Щоб трохи покращити свою відповідь ... вам не потрібно явно
вкладати

Не варто залишати пробілів після встановлення = true або річ просто витончено не працює. Це збереже значення "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.Dat існує, тоді перестрибуйте мітку FILE12_EXIST_LABEL.

Дивитися також: IF /?


53

Закони Де Моргана дозволяють нам перетворити диз'юнкції ("АБО") в логічні еквіваленти, використовуючи лише сполучники ("І") і заперечення ("НЕ"). Це означає, що ми можемо ланцюг диз'юнкцій ("АБО") на одну лінію.

Це означає, що якщо ім'я "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

Це ще одна версія прикладу "АБО" paxdiablo, але умови прив'язані до однієї лінії. (Зверніть увагу , що протилежно leqIS gtrі протилежно geqIS lss.)

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

6

Наступні приклади показують, як зробити оператор AND (використовується для встановлення змінних або включення параметрів для команди).

Щоб запустити Блокнот і закрити вікно 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

Атул Пракаш (на той момент 16 років) дав логічне уявлення про те, як реалізувати тест АБО, заперечуючи умови в операторах IF, а потім використовуючи пункт ELSE як місце розташування коду, який вимагає виконання. Я подумав собі, що, однак, зазвичай потрібні ще два застереження, оскільки він пропонує використовувати два оператори IF, і тому виконаний код потрібно написати два рази . Однак якщо GOTO використовується для пропуску повз необхідного коду, замість того, щоб писати пункти ELSE, код для виконання потрібно написати лише один раз .

Ось тестований приклад того, як я застосував би негативну логіку Атула Пракаша для створення АБО .

У моєму прикладі, комусь дозволяється керувати танком, якщо він має посвідчення танка АБО він проходить військову службу . Введіть true або false за двома підказками, і ви зможете побачити, чи дозволяє логіка керувати цистерною.

@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з &&/ ||і (/ )операторами, щоб досягти того, що ви хочете в одному рядку без будь-яких додаткових змінних та без if-elseдублювання блоків (одна 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

Спробуйте операнд заперечення - "не"!

Ну, якщо ви можете виконати операцію "AND" на операторі if, використовуючи вкладені "if (див. Попередні відповіді), то ви можете зробити те ж саме з операцією" якщо ні ", щоб виконати операцію" або ".

Якщо ви ще не зрозуміли цю ідею, читайте далі. В іншому випадку просто не витрачайте час і повертайтеся до програмування.

Так само, як вкладені "if '' виконуються лише тоді, коли всі умови є істинними," вкладені ", якщо ні - задовольняються лише тоді, коли всі умови помилкові. Це схоже на те, що ви хочете зробити з операндом 'чи', чи не так?

Навіть коли будь-яка з умов вкладеного "якщо ні" є правдою, все твердження залишається невиконаним. Отже, ви можете використовувати заперечення "якщо це послідовно", пам'ятаючи, що тіло заяви про стан повинно бути тим, що ви хочете зробити, якщо всі ваші вкладені умови помилкові. Орган, який ви насправді хотіли дати, повинен підпадати під заяву else.

І якщо ви все ще не отримали суть справи, вибачте, мені 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

Альтернативою є пошук оболонки Unix, яка дає вам логічні оператори та багато іншого. Ви можете отримати власну реалізацію win32 оболонки Bourne тут, якщо не хочете пройти маршрут cygwin. Уродженець Баш можна знайти тут . Я впевнений, що ви можете легко гугл інші хороші альтернативи, такі як zsh або tcsh.

К


4
Якщо ви збираєтеся використати іншу оболонку, принаймні перейдіть з PowerShell: microsoft.com/powershell
Eclipse

17
Є багато кращих снарядів, ніж DOS. Причина, чому я використовував битовий файл DOS, полягає в тому, що він не потребує зовнішніх інструментів. Якщо у вас є клієнт, якому потрібно автоматизувати щось просте, чи дійсно ви хочете, щоб вони мали встановити спеціальні інструменти (cygwin, perl, powerhell тощо), коли файлу BAT буде достатньо?
Марк Лаката

3
BAT вистачає більшості часу. 90% скриптів оболонки Unix ppl запис не є чистою оболонкою, а з багатьма основними програмами, sed, awk тощо. GNU впровадили UNIX-вигоду в інших ОС, включаючи Windows. Тому подивіться на цей getgnuwin32.sourceforge.net cmd.exe / bash / zsh плюс цього має бути достатньо для більшості завдань. Немає причин вивчати так званий PowerShell, якщо у вас є досвід BAT / UNIX Shell
MeaCulpa

0

Тільки АБО частина складна, але із загальним булевим виразом, що містить НЕ АБО І єдине приємне рішення:

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

Незначна модифікація відповіді Ендрі, зменшуючи команди дублікатів типу:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.