C'è un modo per scrivere un'istruzione condizionale IF OR IF in un file batch di Windows?
Per esempio:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
C'è un modo per scrivere un'istruzione condizionale IF OR IF in un file batch di Windows?
Per esempio:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Risposte:
La soluzione zmbq è buona, ma non può essere utilizzata in tutte le situazioni, come all'interno di un blocco di codice come un ciclo FOR DO (...).
Un'alternativa è usare una variabile indicatore. Inizializzalo in modo che non sia definito, quindi definiscilo solo se una delle condizioni OR è vera. Quindi utilizzare SE DEFINITO come test finale, non è necessario utilizzare l'espansione ritardata.
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
Potresti aggiungere la logica ELSE IF che arasmussen usa sulla base del fatto che potrebbe funzionare un po 'più velocemente se la prima condizione è vera, ma non mi preoccupo mai.
Addendum - Questa è una domanda duplicata con risposte quasi identiche a Utilizzo di un OR in un'istruzione IF WinXP Batch Script
Addendum finale : ho quasi dimenticato la mia tecnica preferita per verificare se una variabile è uno qualsiasi di un elenco di valori senza distinzione tra maiuscole e minuscole. Inizializza una variabile di prova contenente un elenco delimitato di valori accettabili, quindi utilizza la funzione di ricerca e sostituzione per verificare se la variabile è inclusa nell'elenco. Questo è molto veloce e utilizza un codice minimo per un elenco arbitrariamente lungo. Richiede un'espansione ritardata (oppure il trucco CALL %% VAR %%). Anche il test è CASE INSENSITIVE.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)
Quanto sopra può fallire se VAR contiene =
, quindi il test non è infallibile.
Se si esegue il test all'interno di un blocco in cui è necessaria un'espansione ritardata per accedere al valore corrente di VAR, allora
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)
)
Opzioni FOR come "delims =" potrebbero essere necessarie a seconda dei valori previsti all'interno di VAR
La strategia di cui sopra può essere resa affidabile anche =
in VAR aggiungendo un po 'più di codice.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true
Ma ora abbiamo perso la capacità di fornire una clausola ELSE a meno che non aggiungiamo una variabile indicatore. Il codice ha cominciato a sembrare un po '"brutto", ma penso che sia il metodo affidabile con le migliori prestazioni per testare se VAR è uno qualsiasi di un numero arbitrario di opzioni senza distinzione tra maiuscole e minuscole.
Infine c'è una versione più semplice che penso sia leggermente più lenta perché deve eseguire un IF per ogni valore. Aacini ha fornito questa soluzione in un commento alla risposta accettata nel collegamento prima citato
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A echo true
L'elenco dei valori non può includere * o? caratteri e i valori e %VAR%
non devono contenere virgolette. Le virgolette creano problemi se %VAR%
contiene anche spazi o caratteri speciali come ^
, &
ecc. Un altro limite di questa soluzione è che non fornisce l'opzione per una clausola ELSE a meno che non si aggiunga una variabile indicatore. I vantaggi sono che può essere sensibile al maiuscolo / minuscolo o insensibile a seconda della presenza o dell'assenza /I
dell'opzione IF .
Non credo proprio. Usa solo due IF e GOTO la stessa etichetta:
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
anche se lo avesse trovato.
Grazie per questo post, mi ha aiutato molto.
Non so se può aiutare ma ho avuto il problema e grazie a te ho trovato quello che penso sia un altro modo per risolverlo basato su questa equivalenza booleana:
"A o B" è uguale a "non (non A e non B)"
Quindi:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Diventa:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
Un semplice "FOR" può essere utilizzato in una singola riga per utilizzare una condizione "o":
FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}
Applicato al tuo caso:
FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
Anche se questa domanda è un po 'più vecchia:
Se vuoi usare if cond1 or cond 2
, non dovresti usare loop complicati o cose del genere.
Fornisci entrambi ifs
uno dopo l'altro in combinazione con goto
- questo è un implicito o.
//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
Senza goto ma un'azione "inplace", potresti eseguire l'azione 3 volte, se TUTTE le condizioni corrispondono.
Non c'è IF <arg> OR
o ELIF
o ELSE IF
in Batch, tuttavia ...
Prova a nidificare gli altri IF all'interno dell'ELSE del precedente IF.
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
È possibile utilizzare una funzione, che valuta la logica OR e restituisce un singolo valore.
@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
)
&& ... || ...
sintassi conveniente direttamente invece IF ... ELSE ...
dell'istruzione extra .
L'obiettivo può essere raggiunto utilizzando gli IF indirettamente.
Di seguito è riportato un esempio di un'espressione complessa che può essere scritta in modo abbastanza conciso e logico in un batch CMD, senza etichette incoerenti e GOTO.
I blocchi di codice tra parentesi quadre () sono gestiti da CMD come un tipo (patetico) di subshell. Qualunque codice di uscita provenga da un blocco verrà utilizzato per determinare il valore vero / falso che il blocco riproduce in un'espressione booleana più grande. Con questi blocchi di codice è possibile costruire espressioni booleane arbitrariamente grandi.
Semplice esempio
Ogni blocco viene risolto in true (ovvero ERRORLEVEL = 0 dopo che l'ultima istruzione nel blocco è stata eseguita) / false, fino a quando il valore dell'intera espressione non è stato determinato o il controllo salta fuori (ad esempio tramite GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
Esempio complesso
Questo risolve il problema sollevato inizialmente. Sono possibili più istruzioni in ogni blocco ma nel campo || || || è preferibile essere conciso in modo che sia il più leggibile possibile. ^ è un carattere di escape nei batch CMD e quando viene posizionato alla fine di una riga uscirà dall'EOL e istruirà CMD a continuare a leggere il batch corrente di istruzioni sulla riga successiva.
@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.
)
)
Serve per verificare se più variabili hanno un valore uguale. Ecco per entrambe le variabili.
If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)
Ho solo pensato a questo dall'alto se la mia testa. Potrei compattarlo di più.
Mi rendo conto che questa domanda è vecchia, ma volevo pubblicare una soluzione alternativa nel caso in cui qualcun altro (come me) avesse trovato questo thread pur avendo la stessa domanda. Sono stato in grado di aggirare la mancanza di un operatore OR facendo eco alla variabile e utilizzando findstr per convalidare.
for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
if %errorlevel% equ 0 echo true
)
Mentre la risposta di dbenham è abbastanza buona, fare affidamento su IF DEFINED
può metterti in un sacco di guai se la variabile che stai controllando non è un ambiente variabile di . Le variabili di script non ricevono questo trattamento speciale.
Anche se questo potrebbe sembrare un ridicolo BS non documentato, facendo una semplice query di shell IF
conIF /?
rivela che,
Il condizionale DEFINED funziona proprio come EXIST tranne per il fatto che richiede un ambiente nome di variabile di e restituisce true se la variabile di ambiente è definita.
Per quanto riguarda la risposta a questa domanda, c'è un motivo per non utilizzare solo un semplice flag dopo una serie di valutazioni? Questo mi sembra il OR
controllo più flessibile , sia per quanto riguarda la logica sottostante che la leggibilità. Per esempio:
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)
Ovviamente, possono essere qualsiasi tipo di valutazione condizionale, ma sto solo condividendo alcuni esempi.
Se vuoi avere tutto su una riga, per quanto riguarda la scrittura, potresti semplicemente incatenarli insieme con &&
come:
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)
Non sono mai esistito per funzionare.
Uso se non esiste g: xyz / what goto h: Altrimenti xcopy c: current / files g: bu / current Ci sono modificatori / a ecc. Non sono sicuro di quali. Computer portatile in negozio. E il computer in ufficio. Non sono li.
Non è mai stato possibile far funzionare i file batch sopra Windows XP
Un'alternativa molto più veloce che di solito uso è la seguente, poiché posso "o" un numero arbitrario di condizioni che possono adattarsi allo spazio variabile
@(
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.
)
Rendendomi conto che questa è una vecchia domanda, le risposte mi hanno aiutato a trovare una soluzione per testare gli argomenti della riga di comando in un file batch; quindi volevo pubblicare anche la mia soluzione nel caso in cui qualcun altro stesse cercando una soluzione simile.
La prima cosa che dovrei sottolineare è che stavo avendo problemi a far funzionare le istruzioni IF ... ELSE all'interno di una clausola FOR ... DO. Risulta (grazie a dbenham per aver inavvertitamente sottolineato questo nei suoi esempi) l'affermazione ELSE non può essere su una riga separata dalle parentesi di chiusura.
Quindi, invece di questo:
FOR ... DO (
IF ... (
)
ELSE (
)
)
Qual è la mia preferenza per la leggibilità e per motivi estetici, devi farlo:
FOR ... DO (
IF ... (
) ELSE (
)
)
Ora l'istruzione ELSE non ritorna come un comando non riconosciuto.
Infine, ecco cosa stavo tentando di fare: volevo essere in grado di passare diversi argomenti a un file batch in qualsiasi ordine, ignorando maiuscole e minuscole e segnalando / fallendo su argomenti non definiti passati. Quindi ecco la mia soluzione ...
@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
Nota, questo riporterà solo il primo argomento fallito. Quindi, se l'utente passa più di un argomento inaccettabile, verrà informato solo del primo fino a quando non viene corretto, quindi del secondo, ecc.
IF [%var%]==[1] IF [%var2%]==[2] ECHO BOTH ARE TRUE
. Ho usato per definireSET AND=IF
e poi scrivere:IF cond1 %AND% cond2 ECHO BOTH ARE TRUE
.