Чи є спосіб написати умовний оператор 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, на тій підставі, що вона може виконуватись трохи швидше, якщо перша умова відповідає дійсності, але я ніколи не турбуюся.
Додаток - це повторне запитання з майже однаковими відповідями на Використання АБО у твердженні IF WinXP Batch Script
Остаточний додаток - я майже забув свою улюблену техніку, щоб перевірити, чи є якась змінна в списку значень, що не враховують регістр. Ініціалізуйте тестову змінну, що містить обмежений список допустимих значень, а потім використовуйте пошук та заміну, щоб перевірити, чи є ваша змінна в списку. Це дуже швидко і використовує мінімальний код для довільно довгого списку. Це вимагає відкладеного розширення (або інакше фокус 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)
)
ДЛЯ опцій типу "delims =" може знадобитися залежно від очікуваних значень у межах VAR
Вищевказану стратегію можна зробити надійною навіть =
у VAR, додавши трохи більше коду.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true
Але тепер ми втратили можливість надати речення ELSE, якщо не додати змінну показника. Код почав виглядати трохи «потворно», але я думаю, що це найкращий надійний метод для перевірки, чи є VAR одним із довільної кількості варіантів, що не враховують регістр.
Нарешті, є простіша версія, яка, на мою думку, є дещо повільнішою, оскільки вона повинна виконувати одну ПІ для кожного значення. 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 %%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, але дії "inplace", ви можете виконати дію 3 рази, якщо ВСІ умови співпадають.
Там немає IF <arg> OR
або ELIF
або 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 ...
оператора.
Ціль може бути досягнута шляхом опосередкованого використання ІФ.
Нижче наведено приклад складного виразу, який можна записати досить стисло та логічно в пакеті CMD, без некогерентних міток та GOTO.
Блоки коду між () дужками обробляються CMD як (жалюгідний) вид підшелупки. Будь-який код виходу, що виходить із блоку, буде використовуватися для визначення істинного / хибного значення, яке відтворює блок у більшому логічному вираженні. За допомогою цих блоків коду можна будувати довільно великі булеві вирази.
Простий приклад
Кожен блок вирішується як true (тобто ERRORLEVEL = 0 після виконання останнього оператора в блоці) / false, поки не буде визначено значення всього виразу або елемент керування не вискочить (наприклад, за допомогою GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
Складний приклад
Це вирішує поставлену спочатку проблему. У кожному блоці можливо декілька операторів, але в || || || вираз бажано бути стислим, щоб він був якомога читабельнішим. ^ є символом екранування в партіях 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, за винятком того, що вона приймає ім'я змінної середовища і повертає true, якщо визначена змінна середовища .
Що стосується відповіді на це питання, чи є причина не просто використовувати простий прапор після серії оцінок? Це здається 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
.