Есть ли способ написать условный оператор IF OR IF в пакетном файле Windows?
Например:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Есть ли способ написать условный оператор IF OR IF в пакетном файле Windows?
Например:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Ответы:
Решение zmbq хорошее, но не может использоваться во всех ситуациях, например, внутри блока кода, такого как цикл FOR DO (...).
Альтернативой является использование индикаторной переменной. Инициализируйте его как неопределенное, а затем определите его, только если выполняется одно из условий ИЛИ. Затем используйте IF DEFINED в качестве финального теста - нет необходимости использовать отложенное расширение.
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
Вы можете добавить логику ELSE IF, которую использует arasmussen на том основании, что она может работать немного быстрее, если 1-е условие истинно, но я никогда не беспокоюсь.
Приложение - это повторяющийся вопрос с почти идентичными ответами на использование оператора ИЛИ в операторе IF. Пакетный сценарий WinXP.
Последнее добавление - я почти забыл свой любимый метод проверки, является ли переменная одним из списков нечувствительных к регистру значений. Инициализируйте тестовую переменную, содержащую список допустимых значений с разделителями, а затем используйте поиск и замену, чтобы проверить, находится ли ваша переменная в списке. Это очень быстро и требует минимального кода для произвольно длинного списка. Это требует отложенного расширения (или трюка CALL %% VAR %%). Также тест НЕ ЧУВСТВИТЕЛЬНЫЙ.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)
Вышеупомянутое может не пройти, если VAR содержит =
, поэтому тест не является надежным.
Если вы выполняете тест в блоке, где требуется отложенное расширение для доступа к текущему значению VAR, тогда
for ... do (
set "TEST=;val1;val2;val3;val4;val5;"
for /f %%A in (";!VAR!;") do if "!TEST:%%A=!" neq "!TEST!" (echo true) else (echo false)
)
Параметры FOR, такие как "delims =", могут потребоваться в зависимости от ожидаемых значений в VAR.
Вышеупомянутую стратегию можно сделать надежной даже =
в VAR, добавив немного больше кода.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true
Но теперь мы потеряли возможность предоставлять предложение ELSE, если мы не добавим индикаторную переменную. Код начал выглядеть немного «некрасиво», но я думаю, что это наиболее эффективный и надежный метод проверки, является ли VAR одним из произвольного числа вариантов без учета регистра.
Наконец, есть более простая версия, которая, на мой взгляд, немного медленнее, потому что она должна выполнять один IF для каждого значения. Aacini предоставил это решение в комментарии к принятому ответу в ранее упомянутой ссылке
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A echo true
Список значений не может включать * или? символы, а значения и %VAR%
не должны содержать кавычек. Цитаты приводят к проблемам, если они %VAR%
также содержат пробелы или специальные символы, например ^
, &
и т. Д. Еще одно ограничение этого решения заключается в том, что оно не предоставляет возможность для предложения ELSE, если вы не добавите индикаторную переменную. Преимущества в том, что он может быть чувствительным к регистру или нечувствительным в зависимости от наличия или отсутствия /I
опции IF .
Я так не думаю. Просто используйте два IF и GOTO с той же меткой:
IF cond1 GOTO foundit
IF cond2 GOTO foundit
ECHO Didn't found it
GOTO end
:foundit
ECHO Found it!
:end
ECHO Didn't find it
даже если он его нашел.
Спасибо за этот пост, он мне очень помог.
Не знаю, может ли это помочь, но у меня возникла проблема, и благодаря вам я нашел, как мне кажется, еще один способ ее решения, основанный на этой логической эквивалентности:
«А или Б» - это то же самое, что «не (не А и не Б)»
Таким образом:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Становится:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
Простое «FOR» может использоваться в одной строке для использования условия «или»:
FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}
Применимо к вашему делу:
FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
Даже если этот вопрос немного старше:
Если хотите использовать if cond1 or cond 2
- не используйте сложные циклы и тому подобное.
Простое предоставление обоих ifs
друг за другом в сочетании с goto
неявным или.
//thats an implicit IF cond1 OR cond2 OR cond3
if cond1 GOTO doit
if cond2 GOTO doit
if cond3 GOTO doit
//thats our else.
GOTO end
:doit
echo "doing it"
:end
Без goto, но с действием «на месте», вы можете выполнить действие 3 раза, если ВСЕ условия совпадают.
Однако в Batch нет IF <arg> OR
или ELIF
или ELSE IF
...
Попробуйте вложить другие IF в ELSE предыдущего IF.
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
Можно использовать функцию, которая оценивает логику ИЛИ и возвращает одно значение.
@echo off
set var1=3
set var2=5
call :logic_or orResult "'%var1%'=='4'" "'%var2%'=='5'"
if %orResult%==1 (
echo At least one expression is true
) ELSE echo All expressions are false
exit /b
:logic_or <resultVar> expression1 [[expr2] ... expr-n]
SETLOCAL
set "logic_or.result=0"
set "logic_or.resultVar=%~1"
:logic_or_loop
if "%~2"=="" goto :logic_or_end
if %~2 set "logic_or.result=1"
SHIFT
goto :logic_or_loop
:logic_or_end
(
ENDLOCAL
set "%logic_or.resultVar%=%logic_or.result%"
exit /b
)
&& ... || ...
синтаксис напрямую вместо дополнительного IF ... ELSE ...
оператора.
Цель может быть достигнута за счет косвенного использования IF.
Ниже приведен пример сложного выражения, которое можно довольно кратко и логично записать в пакете CMD без несогласованных меток и GOTO.
Блоки кода между скобками () обрабатываются CMD как (жалкая) подоболочка. Независимо от того, какой код выхода выходит из блока, он будет использоваться для определения истинного / ложного значения, которое блок воспроизводит в более крупном логическом выражении. С помощью этих блоков кода можно построить произвольно большие логические выражения.
Простой пример
Каждый блок принимает значение true (т.е. ERRORLEVEL = 0 после того, как последний оператор в блоке был выполнен) / false, пока не будет определено значение всего выражения или управление не выйдет (например, через GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
Сложный пример
Это решает изначально возникшую проблему. В каждом блоке возможно несколько операторов, но в || || || выражение желательно быть кратким, чтобы оно было как можно более читаемым. ^ - это escape-символ в пакетах CMD, и если его поместить в конец строки, он выйдет из EOL и проинструктирует CMD продолжить чтение текущего пакета операторов на следующей строке.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(
(CALL :ProcedureType1 a b) ^
|| (CALL :ProcedureType2 sgd) ^
|| (CALL :ProcedureType1 c c)
) ^
&& (
ECHO -=BINGO=-
GOTO :EOF
)
ECHO -=no bingo for you=-
GOTO :EOF
:ProcedureType1
IF "%~1" == "%~2" (EXIT /B 0) ELSE (EXIT /B 1)
GOTO :EOF (this line is decorative as it's never reached)
:ProcedureType2
ECHO :ax:xa:xx:aa:|FINDSTR /I /L /C:":%~1:">nul
GOTO :EOF
If %x%==1 (
If %y%==1 (
:: both are equal to 1.
)
)
Это для проверки того, равны ли значения нескольких переменных. Вот для любой переменной.
If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)
Я просто подумал об этом с головы до ног. Я мог бы сжать его больше.
Я понимаю, что этот вопрос старый, но я хотел опубликовать альтернативное решение на случай, если кто-то еще (например, я) нашел эту ветку, имея тот же вопрос. Мне удалось обойти отсутствие оператора OR, повторив переменную и используя findstr для проверки.
for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
if %errorlevel% equ 0 echo true
)
Хотя ответ dbenham довольно хорош, полагаясь на IF DEFINED
него, вы можете столкнуться с множеством проблем, если проверяемая вами переменная не является средой. переменная переменной . Переменные скрипта не обрабатываются таким специальным образом.
Хотя это может показаться нелепым недокументированным BS, выполнение простого запроса оболочки IF
с помощью IF /?
показывает, что
Условное выражение DEFINED работает так же, как EXIST, за исключением того, что оно принимает имя переменной среды и возвращает истину, если переменная среды определена.
Что касается ответа на этот вопрос, есть ли причина не использовать простой флаг после серии оценок? OR
Мне это кажется наиболее гибкой проверкой как в отношении базовой логики, так и в отношении читабельности. Например:
Set Evaluated_True=false
IF %condition_1%==true (Set Evaluated_True=true)
IF %some_string%=="desired result" (Set Evaluated_True=true)
IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)
IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)
Очевидно, это может быть любая условная оценка, но я просто поделюсь несколькими примерами.
Если вы хотите, чтобы все это было написано в одной строке, вы могли бы просто связать их вместе, &&
например:
Set Evaluated_True=false
IF %condition_1%==true (Set Evaluated_True=true) && IF %some_string%=="desired result" (Set Evaluated_True=true) && IF %set_numerical_variable% EQ %desired_numerical_value% (Set Evaluated_True=true)
IF %Evaluated_True%==true (echo This is where you do your passing logic) ELSE (echo This is where you do your failing logic)
Никогда не существовало, чтобы работать.
Я использую, если не существует g: xyz / what goto h: Else xcopy c: current / files g: bu / current Существуют модификаторы / a и т. Д. Не уверен, какие именно. Ноутбук в магазине. И компьютер в офисе. Меня там нет.
Никогда не получалось, что командные файлы работают над Windows XP
Я обычно использую гораздо более быструю альтернативу: я могу «или» произвольное количество условий, которые могут уместиться в переменном пространстве.
@(
Echo off
Set "_Match= 1 2 3 "
)
Set /a "var=3"
Echo:%_Match%|Find " %var% ">nul || (
REM Code for a false condition goes here
) && (
REM code for a true condition goes here.
)
Понимая, что это немного старый вопрос, ответы помогли мне придумать решение для тестирования аргументов командной строки для пакетного файла; поэтому я также хотел опубликовать свое решение на случай, если кто-то еще искал подобное решение.
Первое, что я должен отметить, это то, что у меня возникли проблемы с тем, чтобы операторы IF ... ELSE работали внутри предложения FOR ... DO. Оказывается (спасибо dbenham за непреднамеренное указание на это в его примерах) оператор ELSE не может находиться в отдельной строке от закрывающих скобок.
Итак, вместо этого:
FOR ... DO (
IF ... (
)
ELSE (
)
)
Что я предпочитаю по удобочитаемости и эстетическим соображениям, вы должны сделать это:
FOR ... DO (
IF ... (
) ELSE (
)
)
Теперь оператор ELSE не возвращается как нераспознанная команда.
Наконец, вот что я пытался сделать - я хотел иметь возможность передавать несколько аргументов в пакетный файл в любом порядке, игнорируя регистр и сообщая / сбой при передаче неопределенных аргументов. Итак, вот мое решение ...
@ECHO OFF
SET ARG1=FALSE
SET ARG2=FALSE
SET ARG3=FALSE
SET ARG4=FALSE
SET ARGS=(arg1 Arg1 ARG1 arg2 Arg2 ARG2 arg3 Arg3 ARG3)
SET ARG=
FOR %%A IN (%*) DO (
SET TRUE=
FOR %%B in %ARGS% DO (
IF [%%A] == [%%B] SET TRUE=1
)
IF DEFINED TRUE (
SET %%A=TRUE
) ELSE (
SET ARG=%%A
GOTO UNDEFINED
)
)
ECHO %ARG1%
ECHO %ARG2%
ECHO %ARG3%
ECHO %ARG4%
GOTO END
:UNDEFINED
ECHO "%ARG%" is not an acceptable argument.
GOTO END
:END
Обратите внимание, это будет сообщать только о первом неудачном аргументе. Таким образом, если пользователь передает более одного неприемлемого аргумента, ему будет рассказано только о первом, пока он не будет исправлен, затем о втором и т. Д.
IF [%var%]==[1] IF [%var2%]==[2] ECHO BOTH ARE TRUE
. Я использовал , чтобы определить ,SET AND=IF
а затем написать:IF cond1 %AND% cond2 ECHO BOTH ARE TRUE
.