Если ... или если... в пакетном файле windows


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

например:

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

13 ответов:

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

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

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

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

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

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

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 do echo true

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

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

IF cond1 GOTO foundit
IF cond2 GOTO foundit

ECHO Didn't found it
GOTO end

:foundit
ECHO Found it!

:end

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

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

"А или Б" - это то же самое, что" не(не А и не б)"

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

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

будет:

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

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

если вы хотите использовать 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 внутри другого предыдущего IF.

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

цель может быть достигнута с помощью IFS косвенно.

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

блоки кода между скобками () обрабатываются 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

можно использовать функцию, которая вычисляет логику 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
) 
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
)

простой " Для "может быть использован в одной строке, чтобы использовать" или " условие:

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

применительно к вашему случаю:

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

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

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

определенные условные работы так же, как существуют, за исключением того, что он принимает окружающая среда имя переменной и возвращает 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 Гото ч: Остальные команды xcopy c:current/files g:bu/current Есть модификаторы / а и др. Не знаю, какие именно. Ноутбук в магазине. И компьютер в офисе. Меня там нет.

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

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

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

Так вместо этого:

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

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

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

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

наконец, вот что я пытался сделать - я хотел иметь возможность передавать несколько аргументов в пакетный файл в любом порядке, игнорируя case и сообщая / отказывая в 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

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