it-roy-ru.com

ЕСЛИ ... OR ЕСЛИ ... в пакетном файле Windows

Можно ли написать условный оператор IF OR IF в пакетном файле Windows?

Например:

IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
76
Mechaflash

Решение zmbq хорошо, но его нельзя использовать во всех ситуациях, например, внутри блока кода, такого как цикл FOR DO (...).

Альтернативой является использование индикаторной переменной. Инициализируйте его как неопределенное, а затем определяйте его, только если выполняется любое из условий OR. Затем используйте IF DEFINED в качестве финального теста - нет необходимости использовать отложенное расширение.

FOR ..... DO (
  set "TRUE="
  IF cond1 set TRUE=1
  IF cond2 set TRUE=1
  IF defined TRUE (
    ...
  ) else (
    ...
  )
)

Вы можете добавить логику ELSE IF, которую использует arasmussen, на том основании, что она может работать чуть быстрее, если выполняется 1-е условие, но я никогда не беспокоюсь.

Приложение - это дублирующий вопрос с почти идентичными ответами на с использованием OR в операторе 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)
)

Могут потребоваться опции 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 do echo true

Список значений не может включать * или? символы, а значения и %VAR% не должны содержать кавычек. Кавычки приводят к проблемам, если %VAR% также содержит пробелы или специальные символы, такие как ^, & и т.д. Еще одно ограничение этого решения заключается в том, что он не предоставляет опцию для предложения ELSE, если вы не добавите переменную-индикатор. Преимущества в том, что он может быть чувствительным к регистру или нечувствительным в зависимости от наличия или отсутствия опции IF /I.

84
dbenham

Я так не думаю. Просто используйте два IF и GOTO одного ярлыка:

IF cond1 GOTO foundit
IF cond2 GOTO foundit

ECHO Didn't found it
GOTO end

:foundit
ECHO Found it!

:end
45
zmbq

Спасибо за этот пост, он мне очень помог.

Не знаю, может ли это помочь, но у меня возникла проблема, и благодаря вам я нашел, как мне кажется, еще один способ ее решения на основе этой логической эквивалентности:

"A или B" - это то же самое, что "нет (не A и не B)"

Таким образом:

IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE

Становится:

IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
6
Cactus

Даже если этот вопрос немного старше:

Если вы хотите использовать 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

Без перехода, кроме действия "на месте", вы можете выполнить действие 3 раза, если ВСЕ условия совпадают.

5
dognose

Однако в пакетном режиме нет IF <arg> OR, Elif или ELSE IF ...

Попробуйте вложить другие IF внутри ELSE предыдущего IF.

IF <arg> (
    ....
) ELSE (
    IF <arg> (
        ......
    ) ELSE (
        IF <arg> (
            ....
        ) ELSE (
    )
)
2
Andrew Rasmussen

Цель может быть достигнута путем косвенного использования IF.

Ниже приведен пример сложного выражения, которое может быть написано достаточно кратко и логически в пакете CMD, без несвязных меток и GOTO.

Блоки кода в скобках () обрабатываются CMD как (жалкий) вид подоболочки. Независимо от того, какой код выхода выходит из блока, будет использоваться для определения истинного/ложного значения, которое блок воспроизводит в большем логическом выражении. С помощью этих блоков кода можно построить произвольно большие логические выражения.

простой пример

Каждый блок разрешается в истину (т.е. ERRORLEVEL = 0 после выполнения последнего оператора в блоке)/ложь, пока не будет определено значение всего выражения или пока не выпадет управление (например, через 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
2
bogdan

Простое "FOR" может использоваться в одной строке для использования условия "или":

FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}  

Применительно к вашему делу:

FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
2
Apostolos

Можно использовать функцию, которая оценивает логику OR и ​​возвращает одно значение.

@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
) 
1
jeb
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
)
)

Я просто подумал об этом с головы до головы. Я мог бы сжать это больше.

1
coltonon

Я понимаю, что этот вопрос старый, но я хотел опубликовать альтернативное решение на тот случай, если кто-то (например, я) найдет эту ветку, имея тот же вопрос. Я смог обойти отсутствие оператора OR, повторив переменную и используя findstr для проверки.

for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
    if %errorlevel% equ 0 echo true
)
1
AKAJim

Хотя ответ dbenham довольно хороший, использование IF DEFINED может доставить вам массу неприятностей, если проверяемая вами переменная не является переменной среды . Переменные скрипта не получают такой специальной обработки.

Хотя это может показаться нелепой недокументированной BS, выполнение простого запроса Shell к IF с IF /? показывает, что

Условное выражение DEFINED работает так же, как EXIST, за исключением того, что оно принимает environment имя переменной и возвращает 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)
0
kayleeFrye_onDeck

Никогда не существует, чтобы работать.

Я использую, если не существует g: xyz/что идет h: остальное xcopy c: текущий/файлы g: bu/current Есть модификаторы/a и т.д. Не уверен, какие из них. Ноутбук в магазине. И компьютер в офисе. Я не там.

Никогда не получал командные файлы для работы выше Windows XP

0
user8865291