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

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

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

Например:

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

Ответ 1

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

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

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

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

Добавление. Это дублированный вопрос с почти идентичными ответами на Использование OR в выражении IF WinXP Batch Script p >

Заключительное дополнение. Я почти забыл свой любимый метод, чтобы проверить, является ли переменная какой-либо из значений. Инициализируйте тестовую переменную, содержащую список допустимых значений, а затем используйте поиск и замену, чтобы проверить, находится ли ваша переменная в списке. Это очень быстро и использует минимальный код для произвольно длинного списка. Это требует отсроченного расширения (или трюк CALL %% VAR %%). Также тест CASE INSENSITIVE.

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 - любое произвольное число без учета регистра параметров.

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

for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A do echo true

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

Ответ 2

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

IF cond1 GOTO foundit
IF cond2 GOTO foundit

ECHO Didn't found it
GOTO end

:foundit
ECHO Found it!

:end

Ответ 3

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

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

"A или B" совпадает с "not (not A, а не B)"

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

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

становится:

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

Ответ 4

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

Если вы хотите использовать 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 раза, если все условия совпадают.

Ответ 5

В пакете нет IF <arg> OR или ELIF или ELSE IF, но...

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

IF <arg> (
    ....
) ELSE (
    IF <arg> (
        ......
    ) ELSE (
        IF <arg> (
            ....
        ) ELSE (
    )
)

Ответ 6

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

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

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

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

Каждый блок имеет значение true (т.е. ERRORLEVEL = 0 после выполнения последнего оператора в блоке)/false до тех пор, пока значение всего выражения не будет определено или управление не выйдет (например, через GOTO):

 ((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)

Сложный пример

Это решает проблему, поднятую первоначально. В каждом блоке возможны несколько операторов, но в || || || выражение предпочтительнее быть кратким, чтобы оно было максимально читаемым. ^ является побегом char в пакетах 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 never reached)

:ProcedureType2
    ECHO :ax:xa:xx:aa:|FINDSTR /I /L /C:":%~1:">nul
GOTO :EOF

Ответ 7

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

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

Ответ 8

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
)
)

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

Ответ 9

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

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

Ответ 10

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

Хотя это может показаться какой-то смехотворной недокументированной 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)

Ответ 11

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

Я использую если не существует g: xyz/what goto h: Else xcopy c: current/files g: bu/current Существуют модификаторы /a и т.д. Не знаете, какие из них. Ноутбук в магазине. И компьютер в офисе. Меня там нет.

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

Ответ 12

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

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

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

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

Ответ 13

Понимая, что это немного старый вопрос, ответы помогли мне придумать решение для тестирования аргументов командной строки в пакетном файле; поэтому я также хотел опубликовать свое решение, если бы кто-то еще искал аналогичное решение.

Первое, что я должен отметить, это то, что у меня возникли проблемы с получением инструкций IF... ELSE для работы внутри предложения FOR... DO. Оказывается (спасибо dbenham за непреднамеренное указание этого в своих примерах) утверждение ELSE не может быть на отдельной строке от закрывающих парнеров.

Итак, вместо этого:

FOR ... DO (
    IF ... (
    )
    ELSE (
    )
)

Каким образом я предпочитаю читаемость и эстетические соображения, вы должны это сделать:

FOR ... DO (
    IF ... (
    ) ELSE (
    )
)

Теперь инструкция ELSE не возвращается как непризнанная команда.

Наконец, вот что я пытался сделать - мне захотелось передать несколько аргументов в пакетный файл в любом порядке, проигнорировав регистр, и сообщив/провалив аргументы undefined, переданные. Итак, вот мое решение...

@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

Обратите внимание, что будет отображаться только первый неудачный аргумент. Поэтому, если пользователь передает более чем один неприемлемый аргумент, им будет сообщено только о первом, пока он не будет исправлен, затем второй и т.д.