Operadores lógicos (“e”, “ou”) no lote do DOS

Respostas:

289

Você pode fazer andcom condições aninhadas:

if %age% geq 2 (
    if %age% leq 12 (
        set class=child
    )
)

ou:

if %age% geq 2 if %age% leq 12 set class=child

Você pode fazer orcom uma variável separada:

set res=F
if %hour% leq 6 set res=T
if %hour% geq 22 set res=T
if "%res%"=="T" (
    set state=asleep
)
paxdiablo
fonte
14
Você também pode usar set res=or or set res=1then, if defined resque é um pouco mais robusto em relação a erros de digitação e funciona mesmo em blocos sem permitir explicitamente a expansão atrasada.
Joey
5
Apenas para melhorar um pouco a sua resposta ... você não precisa aninhar explicitamente as instruções "if" ... você pode simplesmente "encadear" elas, como Dave Jarvis demonstra abaixo
JoelFan
Cuidado para não deixar espaços após o set = true ou a coisa simplesmente não funciona. Ele armazenaria o valor "true" na variável ...
Roland Pihlakas
1
A condição 'ou' que você descreve é ​​lisa e funciona muito bem para um intervalo de números, mas e se eu estiver comparando dois valores independentes, e não um intervalo? Por exemplo, se este arquivo existir ou o nome do arquivo == ""
bakoyaro
1
@bakoyaro, você pode usar qualquer condição para definir res como true, incluindo as que você mencionou.
precisa
69

A IFinstrução não suporta operadores lógicos ( ANDe OR), as IFinstruções em cascata fazem uma conjunção implícita.

IF Exist File1.Dat IF Exist File2.Dat GOTO FILE12_EXIST_LABEL

Se File1.Dat e File1.Dat existir, pule o rótulo FILE12_EXIST_LABEL.

Veja também: IF /?

Dave Jarvis
fonte
53

As leis de De Morgan nos permitem converter disjunções ("OR") em equivalentes lógicos usando apenas conjunções ("AND") e negações ("NÃO"). Isso significa que podemos encadear disjunções ("OR") em uma linha.

Isso significa que se o nome for "Yakko" ou "Wakko" ou "Dot", ecoará "irmão ou irmã Warner".

set warner=true
if not "%name%"=="Yakko" if not "%name%"=="Wakko" if not "%name%"=="Dot" set warner=false
if "%warner%"=="true" echo Warner brother or sister

Esta é outra versão do exemplo "OR" de paxdiablo, mas as condições estão encadeadas em uma linha. (Observe que o oposto de leqé gtre o oposto de geqé lss.)

set res=true
if %hour% gtr 6 if %hour% lss 22 set res=false
if "%res%"=="true" set state=asleep
anômalo
fonte
6

Os exemplos a seguir mostram como criar uma instrução AND (usada para definir variáveis ​​ou incluir parâmetros para um comando).

Para iniciar o Bloco de notas e fechar a janela do CMD:

start notepad.exe & exit

Para definir variáveis ​​x, ye z como valores se a variável 'a' for igual a blá.

IF "%a%"=="blah" (set x=1) & (set y=2) & (set z=3)

Espero que ajude!

GinDiamond
fonte
5

OU é um pouco complicado, mas não excessivamente. Aqui está um exemplo

set var1=%~1
set var2=%~2
::
set or_=
if "%var1%"=="Stack" set or_=true
if "%var2%"=="Overflow" set or_=true
if defined or_ echo Stack OR Overflow
Timo Salmi
fonte
2

Athul Prakash (16 anos na época) deu uma idéia lógica de como implementar um teste OR negando as condições nas instruções IF e, em seguida, usando a cláusula ELSE como local para colocar o código que requer execução. Pensei comigo mesmo que existem duas outras cláusulas normalmente necessárias, pois ele sugere o uso de duas instruções IF e, portanto, o código executado precisa ser escrito duas vezes . No entanto, se um GOTO for usado para ignorar o código necessário, em vez de escrever cláusulas ELSE, o código para execução precisará ser gravado apenas uma vez .

Aqui está um exemplo testável de como eu implementaria a lógica negativa de Athul Prakash para criar um OR .

No meu exemplo, alguém pode dirigir um tanque se tiver uma licença de tanque OU estiver prestando serviço militar . Digite true ou false nos dois prompts e você poderá ver se a lógica permite que você conduza um tanque.

@ECHO OFF
@SET /p tanklicence=tanklicence:
@SET /p militaryservice=militaryservice:

IF /I NOT %tanklicence%==true IF /I NOT %militaryservice%==true GOTO done

ECHO I am driving a tank with tanklicence set to %tanklicence% and militaryservice set to %militaryservice%

:done

PAUSE
Ivan
fonte
2

Se você tiver interesse em escrever uma if+ AND/ ORem uma declaração, não há nenhuma. Mas, você ainda pode grupo ifcom &&/ ||e (/ )declarações para conseguir que você quer em uma linha w / o quaisquer variáveis adicionais e w / o if-elseduplicação bloco (single echode comando para TRUEe FALSEseções de código):

@echo off

setlocal

set "A=1" & set "B=2" & call :IF_AND
set "A=1" & set "B=3" & call :IF_AND
set "A=2" & set "B=2" & call :IF_AND
set "A=2" & set "B=3" & call :IF_AND

echo.

set "A=1" & set "B=2" & call :IF_OR
set "A=1" & set "B=3" & call :IF_OR
set "A=2" & set "B=2" & call :IF_OR
set "A=2" & set "B=3" & call :IF_OR

exit /b 0

:IF_OR
( ( if %A% EQU 1 ( type nul>nul ) else type 2>nul ) || ( if %B% EQU 2 ( type nul>nul ) else type 2>nul ) || ( echo.FALSE-& type 2>nul ) ) && echo TRUE+

exit /b 0

:IF_AND
( ( if %A% EQU 1 ( type nul>nul ) else type 2>nul ) && ( if %B% EQU 2 ( type nul>nul ) else type 2>nul ) && echo.TRUE+ ) || echo.FALSE-


exit /b 0

Saída :

TRUE+
FALSE-
FALSE-
FALSE-

TRUE+
TRUE+
TRUE+
FALSE-

O truque está no typecomando que descarta / define o errorlevele, portanto, lida com o caminho para o próximo comando.

Andry
fonte
1

Experimente o operando da negação - 'não'!

Bem, se você pode executar a operação 'AND' em uma instrução if usando 'if's aninhados (consulte as respostas anteriores), poderá fazer o mesmo com' if not 'para executar uma operação' ou '.

Se você ainda não teve a ideia, continue lendo. Caso contrário, não perca tempo e volte para a programação.

Assim como aninhados 'se' são satisfeitos somente quando todas as condições são verdadeiras, aninhados 'se não são satisfeitos somente quando todas as condições são falsas. Isso é semelhante ao que você deseja fazer com um operando 'ou', não é?

Mesmo quando qualquer uma das condições no aninhado "se não" for verdadeira, a declaração inteira permanecerá insatisfeita. Portanto, você pode usar negados 'if's em sucessão lembrando que o corpo da declaração de condição deve ser o que você deseja fazer se todas as suas condições aninhadas forem falsas. O corpo que você realmente queria dar deveria estar na declaração else.

E se você ainda não entendeu a coisa, desculpe, eu tenho 16 anos e é o melhor que posso fazer para explicar.

Athul Prakash
fonte
x = 2 ou x = 3 =>! ! (x = 2 ou x = 3) =>! (x! = 2 e x! = 3) Não acho que você possa negar o todo se a estrutura aplicar o operador "não" externo necessário. Faz 3 anos, @ Athul-prakash, pensamentos?
Azeroth2b
1

É tão fácil quanto o seguinte:

AND> se + se

if "%VAR1%"=="VALUE" if "%VAR2%"=="VALUE" *do something*

OU> se // se

set BOTH=0
if "%VAR1%"=="VALUE" if "%VAR2%"=="VALUE" set BOTH=1
if "%BOTH%"=="0" if "%VAR1%"=="VALUE" *do something*
if "%BOTH%"=="0" if "%VAR2%"=="VALUE" *do something*

Sei que existem outras respostas, mas acho que a mina é mais simples, mais fácil de entender. Espero que isso ajude você! ;)

Renk Software
fonte
0

Uma alternativa é procurar um shell unix que ofereça operadores lógicos e muito mais. Você pode obter uma implementação nativa do win32 de um shell Bourne aqui se não quiser seguir a rota do cygwin. Uma festa nativa pode ser encontrada aqui . Estou certo de que você poderia facilmente pesquisar no Google outras boas alternativas, como zsh ou tcsh.

K

Kevin Shea
fonte
4
Se você estiver indo para o esforço de usar um shell diferente, pelo menos use o PowerShell: microsoft.com/powershell
Eclipse
17
Existem muitas conchas melhores que o DOS. A razão pela qual eu usaria um arquivo bat do DOS é porque ele não requer nenhuma ferramenta externa. Se você tem um cliente que precisa automatizar algo simples, você realmente quer que ele instale ferramentas especiais (cygwin, perl, powershell etc.) quando um arquivo BAT for suficiente?
21811 Mark Lakata
3
BAT é suficiente na maioria das vezes. 90% dos scripts de shell unix ppl write não são shell puro, mas com muitas chamadas coreutils, sed, awk etc. O GNU implementou itens do UNIX em outro sistema operacional, incluindo o Windows. Portanto, dê uma olhada neste getgnuwin32.sourceforge.net cmd.exe / bash / zsh, mais isso deve ser suficiente na maioria das tarefas. Não há razão para aprender o chamado PowerShell se você tem BAT / UNIX Shell experiência
MeaCulpa
0

Somente a parte OR é complicada, mas com uma expressão booleana geral contendo NOT OR AND a única solução legal é a seguinte:

REM if A == B OR C == C then yes

(call :strequ A B || call :strequ C C) && echo yes
exit /b

:strequ
if "%1" == "%2" exit /b 0
exit /b 1
Henrik4
fonte
-1

Ligeira modificação na resposta de Andry, reduzindo comandos de tipo duplicado:

set "A=1" & set "B=2" & call :IF_AND
set "A=1" & set "B=3" & call :IF_AND
set "A=2" & set "B=2" & call :IF_AND
set "A=2" & set "B=3" & call :IF_AND

echo.

set "A=1" & set "B=2" & call :IF_OR
set "A=1" & set "B=3" & call :IF_OR
set "A=2" & set "B=2" & call :IF_OR
set "A=2" & set "B=3" & call :IF_OR

goto :eof

:IF_OR

(if /i not %A% EQU 1 (
   if /i not %B% EQU 2 (
      echo FALSE-
      type 2>nul
   )
)) && echo TRUE+

goto :eof

:IF_AND


(if /i %A% EQU 1 (
   if /i %B% EQU 2 (
      echo TRUE+
      type 2>nul
   )
)) && echo FALSE-

goto :eof
TedK
fonte