Windows toplu iş dosyasına bir EĞER VEYA EĞER koşullu ifade yazmanın bir yolu var mı?
Örneğin:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Windows toplu iş dosyasına bir EĞER VEYA EĞER koşullu ifade yazmanın bir yolu var mı?
Örneğin:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Yanıtlar:
Zmbq çözümü iyidir, ancak FOR DO (...) döngüsü gibi bir kod bloğunun içinde olduğu gibi tüm durumlarda kullanılamaz.
Bir alternatif, bir gösterge değişkeni kullanmaktır. Tanımlanmamış olacak şekilde başlatın ve ardından yalnızca VEYA koşullarından herhangi biri doğruysa tanımlayın. Ardından son test olarak IF DEFINED'i kullanın - gecikmeli genişletme kullanmaya gerek yoktur.
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
1. koşul doğruysa biraz daha hızlı çalışabileceği gerekçesiyle arasmussen'in kullandığı ELSE EĞER mantığını ekleyebilirsiniz, ancak ben asla rahatsız etmem.
Ek - Bu, WinXP Batch Script IF deyiminde OR kullanma ile neredeyse aynı yanıtlara sahip yinelenen bir sorudur
Son ek - Bir değişkenin büyük / küçük harfe duyarsız değerler listesinden herhangi biri olup olmadığını test etmek için en sevdiğim tekniği neredeyse unutuyordum. Sınırlandırılmış kabul edilebilir değerler listesi içeren bir test değişkenini başlatın ve ardından değişkeninizin listede olup olmadığını test etmek için ara ve değiştir seçeneğini kullanın. Bu çok hızlıdır ve rastgele uzun bir liste için minimum kod kullanır. Gecikmeli genişletme gerektirir (ya da CALL %% VAR %% numarası). Ayrıca test CASE INSENSITIVE'dır.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)
VAR içeriyorsa yukarıdakiler başarısız olabilir =
, bu nedenle test kusursuz değildir.
Testi, VAR'ın mevcut değerine erişmek için gecikmeli genişlemenin gerekli olduğu bir blok içinde yapıyorsanız,
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)
)
VAR içindeki beklenen değerlere bağlı olarak "delims =" gibi seçenekler gerekli olabilir
Yukarıdaki strateji, =
biraz daha fazla kod ekleyerek VAR'da bile güvenilir hale getirilebilir .
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true
Ancak şimdi bir gösterge değişkeni eklemediğimiz sürece bir ELSE cümlesini sağlama yeteneğimizi kaybettik. Kod biraz "çirkin" görünmeye başladı, ancak VAR'ın rastgele sayıdaki büyük / küçük harf duyarlı olmayan seçeneklerden biri olup olmadığını test etmek için en iyi performans gösteren güvenilir yöntem olduğunu düşünüyorum.
Son olarak biraz daha yavaş olduğunu düşündüğüm daha basit bir sürüm var çünkü her değer için bir IF gerçekleştirmesi gerekiyor. Aacini, bu çözümü, daha önce belirtilen bağlantıda kabul edilen yanıta bir yorumda sundu.
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A echo true
Değerler listesi * veya? karakterler ve değerler ve %VAR%
tırnak işareti içermemelidir. Eğer Alıntılar problemlere yol %VAR%
da boşluk veya benzeri özel karakterler içeriyor ^
, &
bu çözümün bir gösterge değişkeni eklemek sürece bir BAŞKA maddede seçeneği sunmaz ise vb bir diğer sınırlama. Avantajları, IF /I
seçeneğinin varlığına veya yokluğuna bağlı olarak büyük / küçük harfe duyarlı veya duyarsız olabilir .
Ben öyle düşünmüyorum. Sadece iki IF kullanın ve aynı etiketi GOTO:
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
.
Bu yazı için teşekkürler, bana çok yardımcı oldu.
Dunno yardımcı olabilirse ama sorun bende vardı ve senin sayende bu boole denkliğine dayanarak sorunu çözmenin başka bir yolu olduğunu düşündüğüm şeyi buldum:
"A veya B", "değil (A ve B değil)" ile aynıdır
Böylece:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Oluyor:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
Basit bir "FOR", bir "veya" koşulunu kullanmak için tek bir satırda kullanılabilir:
FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}
Davanıza uygulandı:
FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
Bu soru biraz daha eski olsa bile:
Kullanmak istiyorsanız if cond1 or cond 2
- karmaşık döngüler veya bunun gibi şeyler kullanmamalısınız.
Basit bir şekilde ifs
birbiri ardına her ikisini de sağlayın goto
- bu örtük veya.
//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
Bir "yerinde" eylem olmadan, TÜM koşullar eşleşiyorsa, eylemi 3 kez yürütebilirsiniz.
Hiçbir yoktur IF <arg> OR
ya ELIF
ya ELSE IF
Ancak Toplu İş ...
Diğer EĞER’leri önceki EĞER’in ELSE’nin içine yerleştirmeyi deneyin.
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
VEYA mantığını değerlendiren ve tek bir değer döndüren bir işlev kullanmak mümkündür.
@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
)
&& ... || ...
, ekstra IF ... ELSE ...
ifade yerine doğrudan uygun sözdizimini kullanabilir .
Hedef, IF'leri dolaylı olarak kullanarak başarılabilir.
Aşağıda, tutarlı olmayan etiketler ve GOTO'lar olmadan bir CMD partisinde oldukça kısa ve mantıklı bir şekilde yazılabilen karmaşık bir ifade örneği bulunmaktadır.
Parantez () arasındaki kod blokları CMD tarafından (acıklı) bir alt kabuk türü olarak ele alınır. Bir bloktan çıkan çıkış kodu ne olursa olsun, bloğun daha büyük bir boole ifadesinde oynadığı doğru / yanlış değeri belirlemek için kullanılacaktır. Bu kod blokları ile rastgele büyük boole ifadeleri oluşturulabilir.
Basit örnek
Her blok, tüm ifadenin değeri belirlenene veya kontrol atlayana kadar (örn. GOTO aracılığıyla) doğru (yani, bloktaki son ifade çalıştırıldıktan sonra ERRORLEVEL = 0) / yanlış olarak çözümlenir:
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
Karmaşık örnek
Bu, başlangıçta ortaya çıkan sorunu çözer. Her blokta birden fazla ifade mümkündür, ancak || || || ifade mümkün olduğunca okunabilir olması için kısa ve öz olması tercih edilir. ^, CMD toplu işlerinde bir kaçış karakteridir ve bir satırın sonuna yerleştirildiğinde EOL'den kaçar ve CMD'ye bir sonraki satırdaki geçerli deyim grubunu okumaya devam etmesini söyler.
@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.
)
)
Bu, birden çok değişkenin eşit değer olup olmadığını kontrol etmek içindir. Her iki değişken için burada.
If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)
Sadece kafamın üstünden düşündüm. Daha fazla sıkıştırabilirim.
Bu sorunun eski olduğunun farkındayım, ancak başka birinin (benim gibi) aynı soruyu sorarken bu konuyu bulması durumunda alternatif bir çözüm göndermek istedim. Değişkeni yankılayarak ve doğrulamak için findstr kullanarak bir OR operatörü eksikliğinden kaçınabildim.
for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
if %errorlevel% equ 0 echo true
)
Dbenham'ın cevabı oldukça iyi IF DEFINED
olsa da, kontrol ettiğiniz değişken bir ortam değişkeni değilse , güvenmek sizi bir sürü belaya sokabilir . Komut dosyası değişkenleri bu özel muameleyi görmez.
Bu bazı saçma belgelenmemiş BS gibi görünse de, IF
ile basit bir kabuk sorgusu yapmak şunu IF /?
ortaya çıkarır:
DEFINED koşulu, bir ortam değişkeni adı alması ve ortam değişkeni tanımlanmışsa true döndürmesi dışında, tıpkı EXIST gibi çalışır .
Bu soruyu cevaplamakla ilgili olarak, bir dizi değerlendirmeden sonra sadece basit bir bayrak kullanmamak için bir neden var mı? Bu OR
, hem mantık hem de okunabilirlik açısından bana en esnek kontrol gibi görünüyor . Örneğin:
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)
Açıkçası, herhangi bir koşullu değerlendirme olabilirler, ancak ben sadece birkaç örnek paylaşıyorum.
Her şeyin yazılı olarak tek bir satırda olmasını istiyorsanız, bunları aşağıdaki &&
gibi zincirleyebilirsiniz :
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)
Asla çalışmak için var olmadı.
Yok ise kullanıyorum g: xyz / what goto h: Else xcopy c: current / files g: bu / current Değiştiriciler var / a vb. Hangileri olduğundan emin değilim. Dükkanda laptop. Ve ofiste bilgisayar. Orada değilim.
Windows XP üzerinde çalışacak toplu iş dosyaları hiç olmadı
Genelde kullandığım çok daha hızlı bir alternatif, değişken alana sığabilecek keyfi sayıda koşul "veya" yapabildiğim için aşağıdaki gibidir
@(
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.
)
Bunun biraz eski bir soru olduğunun farkına varmak, yanıtlar bir toplu iş dosyasında komut satırı argümanlarını test etmek için bir çözüm bulmama yardımcı oldu; Bu nedenle, başka birinin benzer bir çözüm araması durumunda çözümümü de yayınlamak istedim.
İlk belirtmem gereken şey, IF ... ELSE ifadelerinin bir FOR ... DO cümlesinin içinde çalışmasını sağlamakta sorun yaşadığımdır. ELSE ifadesinin, kapanış parantezlerinden ayrı bir satırda olamayacağı ortaya çıktı (örneklerinde istemeden bunu gösterdiği için dbenham sayesinde).
Yani bunun yerine:
FOR ... DO (
IF ... (
)
ELSE (
)
)
Okunabilirlik ve estetik nedenlerle tercihim budur, bunu yapmanız gerekir:
FOR ... DO (
IF ... (
) ELSE (
)
)
Artık ELSE ifadesi tanınmayan bir komut olarak geri dönmüyor.
Son olarak, yapmaya çalıştığım şey şudur - bir toplu iş dosyasına birkaç argümanı herhangi bir sırayla iletebilmek, vakayı görmezden gelerek ve aktarılan tanımsız argümanları bildirmek / başarısız olmak istedim. İşte benim çözümüm ...
@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
Unutmayın, bu sadece ilk başarısız argümanı rapor edecektir. Dolayısıyla, eğer kullanıcı birden fazla kabul edilemez argümandan geçerse, ona sadece birincisi düzeltilene kadar, sonra ikincisi vb. Anlatılacaktır.
IF [%var%]==[1] IF [%var2%]==[2] ECHO BOTH ARE TRUE
. Ben tanımlamak için kullanılanSET AND=IF
ve sonra yazın:IF cond1 %AND% cond2 ECHO BOTH ARE TRUE
.