มีวิธีการเขียนคำสั่งตามเงื่อนไข IF หรือ IF ในไฟล์แบตช์ของ Windows หรือไม่?
ตัวอย่างเช่น:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
มีวิธีการเขียนคำสั่งตามเงื่อนไข IF หรือ IF ในไฟล์แบตช์ของ Windows หรือไม่?
ตัวอย่างเช่น:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
คำตอบ:
โซลูชัน zmbq นั้นดี แต่ไม่สามารถใช้ได้ในทุกสถานการณ์เช่นภายในบล็อกของโค้ดเช่น FOR DO (... ) loop
อีกทางเลือกหนึ่งคือการใช้ตัวแปรตัวบ่งชี้ เริ่มต้นเป็นไม่ได้กำหนดจากนั้นกำหนดก็ต่อเมื่อเงื่อนไข OR ข้อใดข้อหนึ่งเป็นจริง จากนั้นใช้ IF DEFINED เป็นการทดสอบขั้นสุดท้าย - ไม่จำเป็นต้องใช้การขยายที่ล่าช้า
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
คุณสามารถเพิ่มตรรกะ ELSE IF ที่ arasmussen ใช้เนื่องจากอาจทำงานได้เร็วขึ้นเล็กน้อยหากเงื่อนไขที่ 1 เป็นจริง แต่ฉันไม่เคยรำคาญ
ภาคผนวก - นี่เป็นคำถามที่ซ้ำกันซึ่งมีคำตอบเกือบเหมือนกันสำหรับการใช้ OR ในคำสั่ง IF WinXP Batch Script
ภาคผนวกสุดท้าย - ฉันเกือบลืมเทคนิคที่ชื่นชอบในการทดสอบว่าตัวแปรเป็นค่าใดตัวพิมพ์เล็กหรือไม่ เริ่มต้นตัวแปรทดสอบที่มีรายการค่าที่ยอมรับได้แบบคั่นจากนั้นใช้การค้นหาและแทนที่เพื่อทดสอบว่าตัวแปรของคุณอยู่ในรายการหรือไม่ สิ่งนี้เร็วมากและใช้รหัสน้อยที่สุดสำหรับรายการยาว ๆ โดยพลการ ต้องมีการขยายที่ล่าช้า (หรือมิฉะนั้นเคล็ดลับ CALL %% VAR %%) นอกจากนี้การทดสอบยังไม่ไวต่อกรณี
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 เป็นหนึ่งในตัวเลือกที่ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่
ในที่สุดก็มีเวอร์ชันที่ง่ายกว่าที่ฉันคิดว่าช้ากว่าเล็กน้อยเพราะต้องดำเนินการหนึ่ง IF สำหรับแต่ละค่า Aacini ให้วิธีแก้ปัญหานี้ในความคิดเห็นสำหรับคำตอบที่ยอมรับในลิงค์ก่อนหน้านี้
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A echo true
รายการค่าไม่สามารถรวมเครื่องหมาย * หรือ? อักขระและค่าและ%VAR%
ไม่ควรมีเครื่องหมายคำพูด คำคมนำไปสู่ปัญหาถ้า%VAR%
ยังมีช่องว่างหรืออักขระพิเศษเช่น^
, &
ฯลฯ หนึ่งข้อ จำกัด อื่น ๆ ที่มีอยู่ในการแก้ปัญหานี้ก็ไม่ได้ให้ตัวเลือกสำหรับคำสั่งอื่นจนกว่าคุณจะเพิ่มตัวแปรตัวบ่งชี้ ข้อดีคือสามารถพิจารณาตัวพิมพ์เล็กหรือใหญ่โดยขึ้นอยู่กับว่ามีหรือไม่มี/I
ตัวเลือกIF
ฉันไม่คิดอย่างนั้น เพียงใช้สอง IFs และ 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
แม้ว่ามันจะพบก็ตาม
ขอบคุณสำหรับโพสต์นี้มันช่วยฉันได้มาก
Dunno หากสามารถช่วยได้ แต่ฉันมีปัญหาและขอบคุณคุณฉันพบสิ่งที่ฉันคิดว่าเป็นอีกวิธีหนึ่งในการแก้ปัญหาโดยพิจารณาจากความเท่าเทียมกันของบูลีน:
"A หรือ B" เหมือนกับ "not (ไม่ใช่ A และไม่ใช่ B)"
ดังนั้น:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
กลายเป็น:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
สามารถใช้ "FOR" แบบง่ายในบรรทัดเดียวเพื่อใช้เงื่อนไข "หรือ":
FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}
นำไปใช้กับกรณีของคุณ:
FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
แม้ว่าคำถามนี้จะเก่ากว่าเล็กน้อย:
หากคุณต้องการใช้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 แต่เป็นการกระทำ "แทนที่" คุณอาจดำเนินการได้ 3 ครั้งหากเงื่อนไขทั้งหมดตรงกัน
ไม่มีIF <arg> OR
หรือELIF
หรือELSE IF
ในชุด แต่ ...
ลองซ้อน IF อื่น ๆ ภายใน ELSE ของ IF ก่อนหน้า
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
เป็นไปได้ที่จะใช้ฟังก์ชันซึ่งจะประเมินตรรกะ 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 ... ELSE ...
คำสั่งพิเศษ
เป้าหมายสามารถทำได้โดยใช้ IFs ทางอ้อม
ด้านล่างนี้เป็นตัวอย่างของนิพจน์ที่ซับซ้อนซึ่งสามารถเขียนได้อย่างรัดกุมและมีเหตุผลในชุด CMD โดยไม่มีป้ายกำกับและ GOTO ที่ไม่ต่อเนื่องกัน
รหัสบล็อกระหว่าง () วงเล็บถูกจัดการโดย CMD เป็นประเภทย่อย (น่าสมเพช) ไม่ว่าโค้ดออกจากบล็อกใดก็ตามจะถูกใช้เพื่อกำหนดค่าจริง / เท็จที่บล็อกจะเล่นในนิพจน์บูลีนที่ใหญ่กว่า นิพจน์บูลีนขนาดใหญ่ตามอำเภอใจสามารถสร้างขึ้นด้วยบล็อกโค้ดเหล่านี้
ตัวอย่างง่ายๆ
แต่ละบล็อกได้รับการแก้ไขเป็น true (เช่น ERRORLEVEL = 0 หลังจากคำสั่งสุดท้ายในบล็อกได้ดำเนินการ) / false จนกว่าค่าของนิพจน์ทั้งหมดจะถูกกำหนดหรือควบคุมกระโดดออก (เช่นผ่าน GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
ตัวอย่างที่ซับซ้อน
วิธีนี้ช่วยแก้ปัญหาที่เกิดขึ้นในตอนแรก เป็นไปได้หลายคำสั่งในแต่ละบล็อก แต่อยู่ใน || || || นิพจน์ควรกระชับเพื่อให้อ่านง่ายที่สุด ^ เป็นอักขระหลีกในแบทช์ 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
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
)
แม้ว่าคำตอบของ dbenham จะค่อนข้างดี แต่การพึ่งพาIF DEFINED
จะทำให้คุณมีปัญหามากมายหากตัวแปรที่คุณกำลังตรวจสอบไม่ใช่ตัวแปรสภาพแวดล้อม ตัวแปรสคริปต์ไม่ได้รับการปฏิบัติพิเศษนี้
แม้ว่าสิ่งนี้อาจดูเหมือน BS ที่ไม่มีเอกสารที่น่าหัวเราะ แต่การทำแบบสอบถามเปลือกง่ายๆIF
ด้วยการIF /?
เปิดเผยว่า
เงื่อนไข DEFINED ทำงานเช่นเดียวกับ EXIST ยกเว้นจะใช้ ชื่อตัวแปรสภาพแวดล้อมและส่งกลับจริงหากกำหนดตัวแปรสภาพแวดล้อม
ในการตอบคำถามนี้มีเหตุผลอะไรที่จะไม่ใช้เพียงแค่การตั้งค่าสถานะธรรมดา ๆ หลังจากการประเมินชุดต่างๆ ดูเหมือนว่าการ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 goto h: Else xcopy c: current / files g: bu / current มี modifiers / a เป็นต้นไม่แน่ใจว่าตัวไหน แล็ปท็อปในร้านค้า และคอมพิวเตอร์ในสำนักงาน. ฉันไม่ได้อยู่ที่นั่น
ไม่เคยมีไฟล์แบตช์ทำงานเหนือ Windows XP
ทางเลือกที่เร็วกว่ามากที่ฉันมักจะใช้มีดังนี้เท่าที่จะทำได้ "หรือ" จำนวนเงื่อนไขที่กำหนดเองที่สามารถใส่ในพื้นที่ตัวแปรได้
@(
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.
)
การตระหนักว่านี่เป็นคำถามเก่าเล็กน้อยคำตอบช่วยให้ฉันสามารถหาวิธีแก้ปัญหาในการทดสอบอาร์กิวเมนต์บรรทัดคำสั่งกับไฟล์แบตช์ ดังนั้นฉันจึงต้องการโพสต์วิธีแก้ปัญหาของฉันด้วยเผื่อว่าใครกำลังมองหาวิธีแก้ปัญหาที่คล้ายกัน
สิ่งแรกที่ฉันควรชี้ให้เห็นคือฉันมีปัญหาในการรับ IF ... ELSE เพื่อทำงานภายในประโยค FOR ... DO ปรากฎว่า (ขอบคุณ dbenham สำหรับการชี้สิ่งนี้โดยไม่ได้ตั้งใจในตัวอย่างของเขา) คำสั่ง ELSE ไม่สามารถอยู่ในบรรทัดที่แยกต่างหากจาก parens ปิด
แทนที่จะเป็นสิ่งนี้:
FOR ... DO (
IF ... (
)
ELSE (
)
)
ซึ่งเป็นความชอบของฉันสำหรับเหตุผลด้านความสามารถในการอ่านและความสวยงามคุณต้องทำดังนี้
FOR ... DO (
IF ... (
) ELSE (
)
)
ตอนนี้คำสั่ง ELSE ไม่ส่งคืนเป็นคำสั่งที่ไม่รู้จัก
สุดท้ายนี่คือสิ่งที่ฉันพยายามจะทำ - ฉันต้องการให้สามารถส่งข้อโต้แย้งหลาย ๆ ข้อไปยังไฟล์แบตช์ตามลำดับใด ๆ โดยไม่สนใจกรณีและการรายงาน / ล้มเหลวในการโต้แย้งที่ไม่ได้กำหนดที่ส่งผ่านมาดังนั้นนี่คือทางออกของฉัน ...
@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
หมายเหตุนี่จะรายงานเฉพาะอาร์กิวเมนต์แรกที่ล้มเหลว ดังนั้นหากผู้ใช้ส่งผ่านอาร์กิวเมนต์ที่ไม่สามารถยอมรับได้มากกว่าหนึ่งอาร์กิวเมนต์พวกเขาจะได้รับแจ้งเกี่ยวกับอาร์กิวเมนต์แรกเท่านั้นจนกว่าจะได้รับการแก้ไขจากนั้นจึงแก้ไขข้อที่สองเป็นต้น
IF [%var%]==[1] IF [%var2%]==[2] ECHO BOTH ARE TRUE
เลขอะไรคือสิ่งที่เป็นไปได้คือการเขียนโดยตรงและ: ฉันเคยกำหนดSET AND=IF
แล้วเขียน:IF cond1 %AND% cond2 ECHO BOTH ARE TRUE
.