Cmd.exe: сложные условия?
в пакетных файлах DOS. В инструкции IF
можно ли комбинировать два или более условий с использованием AND или OR? Я не смог найти документацию для этого
Изменить - help if
, а документы MS ничего не говорят об использовании более одного условия в if.
Я предполагаю, что обходной путь для И должен был делать
if COND1 (
if COND2 (
cmd
)
)
но это именно то, чего я пытаюсь избежать.
Ответы
Ответ 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 состоит из всех числовых цифр, тогда строки
преобразуется в числа и выполняется цифровое сравнение.