Подтвердить что ты не робот

Cmd.exe: сложные условия?

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

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

Я предполагаю, что обходной путь для И должен был делать

if COND1 (
  if COND2 (
    cmd
  )
)

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

4b9b3361

Ответ 1

Нет, нет более простого способа.

Для 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.

Ответ 2

Я иногда удивляюсь, что люди учатся в школе в наши дни! Конечно, "ИЛИ" тоже возможно. Любая система, которая может предоставить вам "NOT" и "AND", автоматически предоставляет вам "OR", потому что:

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

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

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

... мы должны иметь возможность написать выражение "if (x OR y), то do z", но есть проблема:

Где мы ставим первую "НЕ"? Ну, ответ нигде, мы должны сначала изменить уравнение выше:

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

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

"if ((NOT x) AND (NOT y)), затем (do z)"

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

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

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

"if (NOT p) then (do q) else (do r)"

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

"if (p) then (do r) else (do q)

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

", если (NOT (x OR y)), то (ничего не делать) else (do z)"

Таким образом, мы можем выразить ", если (x OR y) тогда (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

Ответ 3

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

Для обходного пути 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?)

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

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

Ответ 4

Если ваши условия проверяют определенные значения переменной, вы можете настроить ее как оператор 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

Мне не нравится подход Мехрдадской электротехники (цифровой электроники). Хотя точная, с разработкой программного обеспечения, идея, о которой свидетельствует OP, заключается в том, чтобы упростить задачу. Вложенные операторы if добавляют сложность (McCabe). Добавление дополнительных NOTs не помогает.

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

Ответ 5

и

IF <COND1> IF <COND2> ACTION

ИЛИ

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

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

Ответ 6

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

Это непосредственно вставлено из "help if":

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

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

где compare-op может быть одним из:

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. Эти сравнения являются общими, поскольку если строки и Строка 2 состоит из всех числовых цифр, тогда строки преобразуется в числа и выполняется цифровое сравнение.