Existe uma maneira de escrever uma instrução condicional IF OR IF em um arquivo em lote do Windows?
Por exemplo:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Existe uma maneira de escrever uma instrução condicional IF OR IF em um arquivo em lote do Windows?
Por exemplo:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Respostas:
A solução zmbq é boa, mas não pode ser usada em todas as situações, como dentro de um bloco de código como um loop FOR DO (...).
Uma alternativa é usar uma variável indicadora. Inicialize-o como indefinido e, em seguida, defina-o apenas se qualquer uma das condições OR for verdadeira. Em seguida, use IF DEFINED como um teste final - não há necessidade de usar a expansão retardada.
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
Você poderia adicionar a lógica ELSE IF que arasmussen usa, alegando que ele pode ter um desempenho um pouco mais rápido se a primeira condição for verdadeira, mas eu nunca me incomodo.
Adendo - Esta é uma pergunta duplicada com respostas quase idênticas a Usando um OR em uma instrução IF WinXP Batch Script
Adendo final - quase esqueci minha técnica favorita de testar se uma variável faz parte de uma lista de valores que não diferenciam maiúsculas de minúsculas. Inicialize uma variável de teste contendo uma lista delimitada de valores aceitáveis e, em seguida, use pesquisar e substituir para testar se sua variável está na lista. Isso é muito rápido e usa código mínimo para uma lista arbitrariamente longa. Requer expansão atrasada (ou então o truque CALL %% VAR %%). Além disso, o teste é INSENSÍVEL AO CASO.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)
O item acima pode falhar se VAR contiver =
, portanto, o teste não é à prova de erros.
Se estiver fazendo o teste dentro de um bloco onde a expansão atrasada é necessária para acessar o valor atual de VAR, então
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)
)
Opções de FOR como "delims =" podem ser necessárias dependendo dos valores esperados em VAR
A estratégia acima pode se tornar confiável mesmo =
em VAR, adicionando um pouco mais de código.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true
Mas agora perdemos a capacidade de fornecer uma cláusula ELSE, a menos que adicionemos uma variável indicadora. O código começou a parecer um pouco "feio", mas acho que é o método confiável de melhor desempenho para testar se VAR é qualquer um de um número arbitrário de opções que não diferenciam maiúsculas de minúsculas.
Finalmente, há uma versão mais simples que eu acho um pouco mais lenta porque deve realizar um IF para cada valor. Aacini forneceu esta solução em um comentário à resposta aceita no link mencionado anteriormente
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A echo true
A lista de valores não pode incluir * ou? caracteres e os valores e %VAR%
não deve conter aspas. Cotações levar a problemas se o %VAR%
também contém espaços ou caracteres especiais como ^
, &
etc. Uma outra limitação com esta solução é que não oferecem a opção de uma cláusula else menos que você adicione uma variável de indicador. As vantagens são que pode ser sensível a maiúsculas ou não, dependendo da presença ou ausência da /I
opção IF .
Acho que não. Basta usar dois IFs e GOTO no mesmo rótulo:
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
mesmo se ele o encontrasse.
Obrigado por este post, me ajudou muito.
Não sei se isso pode ajudar, mas eu tive o problema e graças a você encontrei o que acho ser outra maneira de resolver com base nesta equivalência booleana:
"A ou B" é o mesmo que "não (não A e não B)"
Portanto:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Torna-se:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
Um simples "PARA" pode ser usado em uma única linha para usar uma condição "ou":
FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}
Aplicado ao seu caso:
FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
Mesmo que esta pergunta seja um pouco mais antiga:
Se você quiser usar if cond1 or cond 2
- você não deve usar loops complicados ou coisas assim.
Simples forneça um ifs
após o outro combinado com goto
- que é um ou implícito.
//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
Sem ir para, mas uma ação "local", você pode executar a ação 3 vezes, se TODAS as condições forem correspondentes.
Não há IF <arg> OR
ou ELIF
ou ELSE IF
em lote, no entanto ...
Tente aninhar os outros IFs dentro do ELSE do IF anterior.
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
É possível usar uma função, que avalia a lógica OR e retorna um único valor.
@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
)
&& ... || ...
sintaxe conveniente diretamente em vez da IF ... ELSE ...
instrução extra .
O objetivo pode ser alcançado usando IFs indiretamente.
Abaixo está um exemplo de uma expressão complexa que pode ser escrita de forma bastante concisa e lógica em um lote CMD, sem rótulos e GOTOs incoerentes.
Blocos de código entre () colchetes são tratados pelo CMD como um tipo (patético) de subshell. Qualquer código de saída que saia de um bloco será usado para determinar o valor verdadeiro / falso que o bloco reproduz em uma expressão booleana maior. Expressões booleanas arbitrariamente grandes podem ser criadas com esses blocos de código.
Exemplo simples
Cada bloco é resolvido para verdadeiro (ou seja, ERRORLEVEL = 0 após a execução da última instrução no bloco) / falso, até que o valor de toda a expressão seja determinado ou o controle salte (por exemplo, via GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
Exemplo complexo
Isso resolve o problema levantado inicialmente. Várias instruções são possíveis em cada bloco, mas no || || || expressão é preferível ser conciso para que seja o mais legível possível. ^ é um caractere de escape em lotes CMD e, quando colocado no final de uma linha, escapará do EOL e instruirá o CMD a continuar lendo o lote atual de instruções na próxima linha.
@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.
)
)
Isso é para verificar se várias variáveis têm valor igual. Aqui está uma das variáveis.
If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)
Eu só pensei nisso de cabeça. Eu poderia compactá-lo mais.
Sei que essa pergunta é antiga, mas gostaria de postar uma solução alternativa caso alguém (como eu) tenha encontrado este tópico e tenha a mesma dúvida. Consegui contornar a falta de um operador OR ecoando a variável e usando findstr para validar.
for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
if %errorlevel% equ 0 echo true
)
Embora a resposta de dbenham seja muito boa, confiar em IF DEFINED
você pode ter muitos problemas se a variável que você está verificando não for uma variável de ambiente . Variáveis de script não recebem este tratamento especial.
Embora isso possa parecer algum BS indocumentado ridículo, fazer uma consulta shell simples de IF
com IF /?
revela que,
A condicional DEFINED funciona exatamente como EXIST, exceto que recebe um nome de variável de ambiente e retorna true se a variável de ambiente for definida.
Em relação a responder a essa pergunta, há uma razão para não usar apenas um sinalizador simples após uma série de avaliações? Essa parece a OR
verificação mais flexível para mim, tanto em relação à lógica subjacente quanto à legibilidade. Por exemplo:
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)
Obviamente, eles podem ser qualquer tipo de avaliação condicional, mas estou apenas compartilhando alguns exemplos.
Se você quiser ter tudo em uma linha, por escrito, você pode apenas encadea-los juntos &&
como:
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)
Nunca existiu para funcionar.
Eu uso se não existir g: xyz / what goto h: Else xcopy c: current / files g: bu / current Existem modificadores / a etc. Não tenho certeza de quais. Laptop na loja. E o computador no escritório. Eu não estou aí.
Arquivos em lote nunca funcionaram acima do Windows XP
Uma alternativa muito mais rápida que costumo usar é a seguinte, pois posso "ou" um número arbitrário de condições que podem caber em espaço variável
@(
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.
)
Percebendo que esta é uma questão um pouco antiga, as respostas me ajudaram a encontrar uma solução para testar argumentos de linha de comando em um arquivo em lote; então eu queria postar minha solução também, caso alguém mais estivesse procurando por uma solução semelhante.
A primeira coisa que devo ressaltar é que estava tendo problemas para fazer com que as instruções IF ... ELSE funcionassem dentro de uma cláusula FOR ... DO. Acontece que (graças a dbenham por inadvertidamente apontar isso em seus exemplos) a instrução ELSE não pode estar em uma linha separada dos parênteses de fechamento.
Então, em vez disso:
FOR ... DO (
IF ... (
)
ELSE (
)
)
Qual é a minha preferência por razões de legibilidade e estética, você tem que fazer isso:
FOR ... DO (
IF ... (
) ELSE (
)
)
Agora, a instrução ELSE não retorna como um comando não reconhecido.
Finalmente, eis o que eu estava tentando fazer - eu queria ser capaz de passar vários argumentos para um arquivo em lote em qualquer ordem, ignorando o caso e relatando / falhando em argumentos indefinidos transmitidos. Então, aqui está minha solução ...
@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
Observe que isso reportará apenas no primeiro argumento com falha. Portanto, se o usuário transmitir mais de um argumento inaceitável, ele só será informado sobre o primeiro até que seja corrigido, depois sobre o segundo, etc.
IF [%var%]==[1] IF [%var2%]==[2] ECHO BOTH ARE TRUE
. I utilizado para definirSET AND=IF
e, em seguida, escrever:IF cond1 %AND% cond2 ECHO BOTH ARE TRUE
.