Có cách nào để viết câu lệnh điều kiện IF HOẶC IF trong một tệp lô cửa sổ không?
Ví dụ:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Có cách nào để viết câu lệnh điều kiện IF HOẶC IF trong một tệp lô cửa sổ không?
Ví dụ:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Câu trả lời:
Giải pháp zmbq là tốt, nhưng không thể được sử dụng trong mọi trường hợp, chẳng hạn như bên trong một khối mã như vòng lặp FOR DO (...).
Một giải pháp thay thế là sử dụng một biến chỉ số. Khởi tạo nó thành không xác định, và sau đó xác định nó chỉ khi bất kỳ một trong các điều kiện OR là đúng. Sau đó sử dụng IF DEFINED như một thử nghiệm cuối cùng - không cần sử dụng mở rộng bị trì hoãn.
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
Bạn có thể thêm logic ELSE IF mà arasmussen sử dụng với lý do rằng nó có thể hoạt động nhanh hơn một chút nếu điều kiện đầu tiên là đúng, nhưng tôi không bao giờ bận tâm.
Phụ lục - Đây là một câu hỏi trùng lặp với các câu trả lời gần giống nhau cho Sử dụng OR trong câu lệnh IF WinXP Batch Script
Phụ lục cuối cùng - Tôi gần như đã quên kỹ thuật yêu thích của mình để kiểm tra xem một biến có phải là bất kỳ một trong danh sách các giá trị không phân biệt chữ hoa chữ thường hay không. Khởi tạo một biến thử nghiệm có chứa danh sách được phân tách bằng các giá trị được chấp nhận, sau đó sử dụng tìm kiếm và thay thế để kiểm tra xem biến của bạn có nằm trong danh sách hay không. Điều này rất nhanh và sử dụng mã tối thiểu cho một danh sách dài tùy ý. Nó yêu cầu mở rộng bị trì hoãn (hoặc nếu không, thủ thuật CALL %% VAR %%). Ngoài ra, bài kiểm tra là CASE INSENSITIVE.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)
Ở trên có thể không thành công nếu VAR có chứa =
, vì vậy thử nghiệm không phải là thử nghiệm đánh lừa.
Nếu thực hiện kiểm tra trong một khối nơi cần mở rộng trễ để truy cập giá trị hiện tại của VAR thì
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)
)
Các tùy chọn FOR như "delims =" có thể cần thiết tùy thuộc vào các giá trị mong đợi trong VAR
Chiến lược trên có thể được thực hiện đáng tin cậy ngay cả với =
VAR bằng cách thêm một chút mã.
set "TEST=;val1;val2;val3;val4;val5;"
if "!TEST:;%VAR%;=!" neq "!TEST!" if "!TEST:;%VAR%;=;%VAR%;"=="!TEST!" echo true
Nhưng bây giờ chúng tôi đã mất khả năng cung cấp một mệnh đề ELSE trừ khi chúng tôi thêm một biến chỉ số. Mã đã bắt đầu trông hơi "xấu", nhưng tôi nghĩ rằng đó là phương pháp đáng tin cậy hoạt động tốt nhất để kiểm tra nếu VAR là bất kỳ một trong số các tùy chọn phân biệt chữ hoa chữ thường tùy ý.
Cuối cùng, có một phiên bản đơn giản hơn mà tôi nghĩ là hơi chậm hơn vì nó phải thực hiện một IF cho mỗi giá trị. Aacini đã cung cấp giải pháp này trong một bình luận cho câu trả lời được chấp nhận trong liên kết được đề cập trước đó
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A echo true
Danh sách các giá trị không được bao gồm dấu * hoặc? ký tự và các giá trị và %VAR%
không được chứa dấu ngoặc kép. Dấu ngoặc kép dẫn đến sự cố nếu %VAR%
dấu ngoặc kép cũng chứa khoảng trắng hoặc các ký tự đặc biệt như ^
, &
v.v. Một hạn chế khác với giải pháp này là nó không cung cấp tùy chọn cho mệnh đề ELSE trừ khi bạn thêm một biến chỉ số. Ưu điểm là nó có thể phân biệt chữ hoa chữ thường hoặc không phân biệt tùy thuộc vào sự hiện diện hoặc không có /I
tùy chọn IF .
Tôi không nghĩ vậy. Chỉ cần sử dụng hai IF và GOTO cùng một nhãn:
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
ngay cả khi nó tìm thấy.
Cảm ơn cho bài viết này, nó đã giúp tôi rất nhiều.
Dunno nếu nó có thể giúp nhưng tôi đã gặp vấn đề và nhờ bạn, tôi đã tìm thấy những gì tôi nghĩ là một cách khác để giải quyết nó dựa trên sự tương đương boolean này:
"A hoặc B" giống với "not (không phải A và không phải B)"
Như vậy:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Trở thành:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
Một "FOR" đơn giản có thể được sử dụng trong một dòng để sử dụng điều kiện "hoặc":
FOR %%a in (item1 item2 ...) DO IF {condition_involving_%%a} {execute_command}
Áp dụng cho trường hợp của bạn:
FOR %%a in (1 2) DO IF %var%==%%a ECHO TRUE
Ngay cả khi câu hỏi này cũ hơn một chút:
Nếu bạn muốn sử dụng if cond1 or cond 2
- bạn không nên sử dụng các vòng lặp phức tạp hoặc những thứ như vậy.
Đơn giản cung cấp cả hai ifs
sau khi nhau kết hợp với goto
- đó là một ẩn hoặc.
//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
Không có goto mà là một hành động "tại chỗ", bạn có thể thực hiện hành động 3 lần, nếu TẤT CẢ các điều kiện đều phù hợp.
Tuy nhiên, không có IF <arg> OR
hoặc ELIF
hoặc ELSE IF
theo lô ...
Thử lồng IF khác bên trong ELSE của IF trước đó.
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
Có thể sử dụng một hàm đánh giá logic OR và trả về một giá trị duy nhất.
@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
)
&& ... || ...
cú pháp thuận tiện trực tiếp thay vì IF ... ELSE ...
câu lệnh phụ .
Mục tiêu có thể đạt được bằng cách sử dụng các IF gián tiếp.
Dưới đây là ví dụ về một biểu thức phức tạp có thể được viết khá ngắn gọn và logic trong một lô CMD, không có nhãn và GOTO không mạch lạc.
Các khối mã giữa () ngoặc được CMD xử lý như một loại vỏ con (thảm hại). Bất kỳ mã thoát nào xuất phát từ một khối sẽ được sử dụng để xác định giá trị true / false mà khối đóng trong một biểu thức boolean lớn hơn. Các biểu thức boolean lớn tùy ý có thể được xây dựng bằng các khối mã này.
Ví dụ đơn giản
Mỗi khối được giải quyết thành true (tức là ERRORLEVEL = 0 sau khi câu lệnh cuối cùng trong khối được thực thi) / false, cho đến khi giá trị của toàn bộ biểu thức đã được xác định hoặc điều khiển nhảy ra (ví dụ: thông qua GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
Ví dụ phức tạp
Điều này giải quyết vấn đề được nêu ra ban đầu. Có thể có nhiều câu lệnh trong mỗi khối nhưng trong dấu || || || diễn đạt tốt hơn nên ngắn gọn để dễ đọc nhất có thể. ^ là một ký tự thoát trong lô CMD và khi được đặt ở cuối dòng, nó sẽ thoát khỏi EOL và hướng dẫn CMD tiếp tục đọc lô câu lệnh hiện tại ở dòng tiếp theo.
@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.
)
)
Đó là để kiểm tra xem nhiều biến có giá trị bằng nhau hay không. Đây là cho một trong hai biến.
If %x%==1 (
:: true
)
If %x%==0 (
If %y%==1 (
:: true
)
)
If %x%==0 (
If %y%==0 (
:: False
)
)
Tôi chỉ nghĩ về điều đó khỏi đầu nếu đầu của tôi. Tôi có thể thu gọn nó nhiều hơn.
Tôi nhận ra câu hỏi này đã cũ, nhưng tôi muốn đăng một giải pháp thay thế trong trường hợp bất kỳ ai khác (như tôi) tìm thấy chủ đề này trong khi có cùng câu hỏi. Tôi đã có thể khắc phục việc thiếu toán tử OR bằng cách lặp lại biến và sử dụng findstr để xác thực.
for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do (
if %errorlevel% equ 0 echo true
)
Mặc dù câu trả lời của dbenham khá hay, nhưng việc dựa vào IF DEFINED
có thể khiến bạn gặp vô số rắc rối nếu biến bạn đang kiểm tra không phải là biến môi trường . Các biến tập lệnh không được xử lý đặc biệt này.
Mặc dù điều này có vẻ giống như một số BS không có giấy tờ lố bịch, nhưng thực hiện một truy vấn shell đơn giản IF
với with IF /?
cho thấy rằng,
Điều kiện DEFINED hoạt động giống như EXIST ngoại trừ nó nhận một tên biến môi trường và trả về true nếu biến môi trường được xác định.
Liên quan đến việc trả lời câu hỏi này, có lý do gì để không chỉ sử dụng một lá cờ đơn giản sau một loạt các đánh giá? Đó dường như là cách OR
kiểm tra linh hoạt nhất đối với tôi, cả về logic cơ bản và khả năng đọc. Ví dụ:
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)
Rõ ràng, chúng có thể là bất kỳ loại đánh giá có điều kiện nào, nhưng tôi chỉ chia sẻ một vài ví dụ.
Nếu bạn muốn có tất cả trên một dòng, thông minh bằng văn bản, bạn có thể chuỗi chúng lại với nhau bằng cách &&
như:
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)
Không bao giờ tồn tại để làm việc.
Tôi sử dụng nếu không tồn tại g: xyz / what goto h: Khác xcopy c: current / files g: bu / current Có bổ ngữ / a, v.v. Không chắc cái nào. Máy tính xách tay tại cửa hàng. Và máy tính trong văn phòng. Tôi không có ở đó.
Không bao giờ có tệp hàng loạt hoạt động trên Windows XP
Một giải pháp thay thế nhanh hơn nhiều mà tôi thường sử dụng như sau, vì tôi có thể "hoặc" một số điều kiện tùy ý có thể phù hợp với không gian biến đổi
@(
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.
)
Nhận thấy đây là một câu hỏi hơi cũ, các câu trả lời đã giúp tôi đưa ra giải pháp để kiểm tra các đối số dòng lệnh cho một tệp loạt; vì vậy tôi cũng muốn đăng giải pháp của mình trong trường hợp có ai khác đang tìm kiếm giải pháp tương tự.
Điều đầu tiên mà tôi nên chỉ ra là tôi đã gặp khó khăn khi đưa các câu lệnh IF ... ELSE hoạt động bên trong mệnh đề FOR ... DO. Hóa ra (cảm ơn dbenham đã vô tình chỉ ra điều này trong các ví dụ của anh ấy) câu lệnh ELSE không thể nằm trên một dòng riêng biệt với các parens đóng.
Vì vậy, thay vì điều này:
FOR ... DO (
IF ... (
)
ELSE (
)
)
Sở thích của tôi vì lý do dễ đọc và thẩm mỹ, bạn phải làm điều này:
FOR ... DO (
IF ... (
) ELSE (
)
)
Bây giờ câu lệnh ELSE không trả về như một lệnh không được công nhận.
Cuối cùng, đây là những gì tôi đang cố gắng thực hiện - tôi muốn có thể chuyển một số đối số vào một tệp hàng loạt theo bất kỳ thứ tự nào, bỏ qua chữ hoa chữ thường và báo cáo / không thành công trên các đối số không xác định được truyền vào. Vì vậy, đây là giải pháp của tôi ...
@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
Lưu ý, điều này sẽ chỉ báo cáo về đối số không thành công đầu tiên. Vì vậy, nếu người dùng chuyển nhiều hơn một đối số không được chấp nhận, họ sẽ chỉ được thông báo về đối số đầu tiên cho đến khi nó được sửa, sau đó là đối số thứ hai, v.v.
IF [%var%]==[1] IF [%var2%]==[2] ECHO BOTH ARE TRUE
. Tôi sử dụng để xác địnhSET AND=IF
và sau đó viết:IF cond1 %AND% cond2 ECHO BOTH ARE TRUE
.