cmd.exe: сложные условия? - PullRequest
13 голосов
/ 05 мая 2010

в пакетных файлах DOS. В операторе IF возможно ли объединить два или более условий, используя AND или OR? Я не смог найти никакой документации для этого

Edit - help if и документы MS ничего не говорят об использовании более одного условия в if.

Я думаю, что обходной путь для И будет делать

if COND1 (
  if COND2 (
    cmd
  )
)

но это именно то, чего я пытаюсь избежать.

Ответы [ 6 ]

14 голосов
/ 05 мая 2010

Нет, более легкого пути нет.

Для and вы также можете просто связать их в цепочку, не вводя блоки:

if COND1 if COND2 ...

что, честно говоря, не хуже, чем

if COND1 and COND2 ...

Тем не менее, для or это становится действительно ужаснее:

set COND=
if COND1 set COND=1
if COND2 set COND=1
if defined COND ...

или

if COND1 goto :meh
if COND2 goto :meh
goto :meh2
:meh
...
:meh2

Однажды я увидел пакетный препроцессор, который использовал C-подобный синтаксис для потока управления и пакетного содержимого между ними, а затем преобразовал такие условия в несколько переходов и проверок. Тем не менее, это было для пакетных файлов DOS и было практически бесполезным в среде Windows.

9 голосов
/ 28 марта 2013

Я иногда задаюсь вопросом, чему сейчас учат в школе! Конечно, «ИЛИ» тоже возможно. Любая система, которая может предоставить вам «НЕ» и «И», автоматически также предоставляет вам «ИЛИ», потому что:

x ИЛИ y = НЕ ((НЕ x) И (НЕ y)) см. http://en.wikipedia.org/wiki/De_Morgan%27s_laws

Так что до тех пор, пока выражение "if (x AND y) then do z" можно записать так:

if (x) if (y) (do z)

... мы должны быть в состоянии написать выражение «если (x ИЛИ y), то сделать z», , но есть проблема:

Где мы должны поставить первое «НЕ»? Ну, ответ никуда, мы должны сначала преобразовать уравнение выше:

НЕ (x ИЛИ y) = (НЕ x) И (НЕ y)

В соответствии с этим мы можем написать «if (NOT (x OR y)) then (do z)» как:

"if ((НЕ x) И (НЕ y)) тогда (do z)"

Имея это и зная, как выразить AND, как показано выше, мы можем теперь написать выражение «if (NOT (x OR y)) then (do z)» как:

if (not x) if (not y) (REM do z)

Мы также знаем, что выражение:

"если (НЕ р), то (сделать q), еще (сделать r)"

... эквивалентно:

"if (p), то (do r) else (do q)

Таким образом, мы можем написать «if (x OR y) then (do z)»:

"если (НЕ (x ИЛИ y)), то (ничего не делать), иначе (делать z)"

Таким образом, мы можем выразить "if (x OR y) then (do z)" как:

if (not x) if (not y) (REM do nothing) else (REM do z)

Но это еще не все, потому что это не истинное "И", а "имитированное". Чего не хватает, так это второго. Таким образом, полная форма для получения правильного результата должна быть:

if (not x) ( if (not y) (REM do nothing) else (REM do z) ) else (REM do z) )

... у которого есть уродливая двойная другая часть. Вы можете решить это с помощью 'goto', и мы наконец имеем:

rem if (x OR y) then (do z):
if (not x) ( if (not y) (goto :doNothing) )
rem do z
:doNothing
2 голосов
/ 15 ноября 2012

Для обходного пути И я согласен с Джои, я не вижу другого решения.

Для обходного решения OR я бы предложил следующий «трюк»:
Допустим, вы хотите проверить, обращался ли пользователь за помощью в командной строке при вызове вашего пакетного файла, что-то вроде: thebatch /?.
Но вы не знаете, будет ли пользователь печатать /?, а точнее (будучи пользователем, привыкшим к Unix) --help или -h, или даже вообще забудет передать какой-либо аргумент.

Ваш код может быть таким:

for %%P in ("" "-h" "--help") do if "%1"==%%P (
   :help
   echo this is my help...  >&2
   exit /b 9
)

Обратите внимание, что тестирование "/?" или же "-?" с этим трюком строки работать не будут (петли FOR не любят метасимвол ?).
Для этого просто добавьте строку: if "%1"=="/?" goto help в верхней части блока (см. Метку ':help' внутри for loop ?)

Обратите внимание, что этот синтаксис не будет работать (он просто полностью игнорируется и код не будет выполняться) с пакетными файлами в TCC.EXE (интерпретатор Take Command, полная или облегченная версия), но в этом случае просто используйте их синтаксис с ключевыми словами .OR. и .AND..

Надеюсь, это поможет.

0 голосов
/ 16 февраля 2016

И

IF <COND1> IF <COND2> ACTION

OR

(SET _=) & (IF <COND1> (SET _= ) ELSE IF <COND2> (SET _= )) & IF DEFINED _ ACTION

Для реализации ИЛИ таким способом вам нужны расширения команд.

0 голосов
/ 02 декабря 2014

Если ваши условия проверяют конкретные значения переменной, вы можете установить ее как оператор CASE.Мне нужно было проверить, был ли ТИП отдельным участником или группой (или все) .

Примечание: метки не чувствительны к регистру.

Если любое из условий истинно (если TYPE==ALL или TYPE==GROUP1 или TYPE==GROUP2) , тогда выполняется кодовый блок, в противном случае выполнение пропускается через блок.

goto :TYPE_EQ_%TYPE% 2>NUL
if %ERRORLEVEL% neq 0 goto :END_CASE_TYPE
:TYPE_EQ_ALL
:TYPE_EQ_GROUP1
:TYPE_EQ_GROUP2
rem do what you need
   echo GROUP: %TYPE%
:END_CASE_TYPE

Мне не нравится электротехника Мердада (цифровая электроника) подход.Идея, как указывает ОП, хотя и точна, но с точки зрения разработки программного обеспечения, состоит в том, чтобы упростить процесс выяснения.Вложено, если операторы добавляют Сложность (МакКейб) .Добавление дополнительных NOT не помогает.

Мое решение немного странно, если вы не знаете настройки goto-label / error, но это плоская структура, которая приблизительно настроена как if-оператор с несколькими условиями OR, которые нетрудно расшифровать.

0 голосов
/ 05 мая 2010

Пока включены расширения команд, вы можете использовать операторы сравнения.

Это напрямую вставляется из "help if":

Если включены расширения команд, ЕСЛИ изменяется следующим образом:

IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command

, где сравнение может быть одним из:

EQU - equal
NEQ - not equal
LSS - less than
LEQ - less than or equal
GTR - greater than
GEQ - greater than or equal

и переключатель / I, если указан, говорит, что нужно делать строку без учета регистра сравнивает. Переключатель / I также можно использовать в форме string1 == string2 из IF. Эти сравнения являются общими, в том случае, если как string1, так и строка2 состоит из всех числовых цифр, тогда строки конвертируется в числа и выполняется числовое сравнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...