IF …或IF …在Windowsbatch file中
有没有办法在Windowsbatch file中写入IF或IF条件语句?
例如:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
zmbq解决scheme很好,但不能在所有情况下使用,例如像FOR DO(…)循环这样的代码块。
另一种方法是使用指标variables。 将其初始化为未定义,然后仅在OR条件中的任何一个为真时才定义它。 然后使用IF DEFINED作为最终testing – 不需要使用延迟扩展。
FOR ..... DO ( set "TRUE=" IF cond1 set TRUE=1 IF cond2 set TRUE=1 IF defined TRUE ( ... ) else ( ... ) )
如果第一个条件成立,你可以添加arasmussen使用的ELSE IF逻辑,理由是如果第一个条件成立,它可能会执行得更快一些,但是我从不打扰。
附录 – 这是一个重复的问题, 在IF语句WinXP批处理脚本中使用OR几乎相同
最后的附录 – 我几乎忘记了我最喜欢的技术来testingvariables是否是值列表中的任何一个。 初始化包含可接受值的分隔列表的testingvariables,然后使用search和replace来testingvariables是否在列表中。 这是非常快速的,并使用最小的代码为一个任意长的名单。 它需要延迟扩展(或者CALL %% VAR %%技巧)。 此外,testing是CASE INSENSITIVE。
set "TEST=;val1;val2;val3;val4;val5;" if "!TEST:;%VAR%;=!" neq "!TEST!" (echo true) else (echo false)
如果VAR包含=
,以上可能会失败,所以testing不是傻瓜。
如果在需要延迟扩展的块内进行testing,才能访问当前的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子句的能力,除非我们添加一个指示variables。 代码已经开始看起来有点“丑陋”,但是我认为这是testingperformance最好的可靠方法,如果VAR是任意数量的不区分大小写的选项中的任何一个。
最后还有一个更简单的版本,我认为它稍微慢一点,因为它必须为每个值执行一个IF。 Aacini在前面提到的链接中接受的答案中提供了这个解决scheme
for %%A in ("val1" "val2" "val3" "val4" "val5") do if "%VAR%"==%%A do echo true
值的列表不能包含*或? 字符,值和%VAR%
不应包含引号。 如果%VAR%
还包含空格或特殊字符(如^
, &
等),则引号会导致问题。此解决scheme的另一个限制是,除非添加指示符variables,否则不会为ELSE子句提供选项。 优点是它可以区分大小写或不敏感,取决于是否存在IF /I
选项。
我不这么认为。 只需使用两个IF和GOTO相同的标签:
IF cond1 GOTO foundit IF cond2 GOTO foundit ECHO Didn't found it GOTO end :foundit ECHO Found it! :end
感谢这篇文章,它帮了我很多。
不知道,如果它可以帮助,但我有这个问题,并感谢你,我发现我认为是另一种方法来解决它基于这个布尔等价:
“A或B”与“不(不是A而不是B)”相同
从而:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
变为:
IF not [%var%] == [1] IF not [%var%] == [2] ECHO FALSE
在批处理中没有IF <arg> OR
或ELIF
或ELSE IF
,但是…
尝试嵌套在以前IF的ELSE中的其他IF。
IF <arg> ( .... ) ELSE ( IF <arg> ( ...... ) ELSE ( IF <arg> ( .... ) ELSE ( ) )
即使这个问题有点老:
如果你想使用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
没有转到,而是一个“inplace”动作,如果ALL条件匹配,你可以执行动作3次。
目标可以通过间接使用IF来实现。
下面是一个复杂expression式的例子,它可以在一个CMD批次中相当简洁和逻辑地编写,而不会有不连贯的标签和GOTO。
()括号之间的代码块由CMD作为(可怜的)types的子shell来处理。 无论块出来的退出代码将被用来确定块在更大的布尔expression式中所起的真/假值。 任意大的布尔expression式可以用这些代码块build立。
简单的例子
每个块被parsing为真(即在块中最后一个语句执行后ERRORLEVEL = 0)/ false,直到整个expression式的值已经被确定或者控制跳出(例如通过GOTO):
((DIR c:\xsgdde /w) || (DIR c:\ /w)) && (ECHO -=BINGO=-)
复杂的例子
这解决了最初提出的问题。 在每个块中可以有多个语句,但在||中是可能的 || || expression式最好简洁一些,以使其尽可能可读。 ^是CMD批处理中的一个转义字符,当放在一行的末尾时,它将跳过EOL并指示CMD继续读取下一行中的当前批处理语句。
@ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION ( (CALL :ProcedureType1 ab) ^ || (CALL :ProcedureType2 sgd) ^ || (CALL :ProcedureType1 cc) ) ^ && ( 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
可以使用一个函数来计算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 %x%==1 ( If %y%==1 ( :: both are equal to 1. ) )
这是为了检查多个variables是否等价。 这是两个variables。
If %x%==1 ( :: true ) If %x%==0 ( If %y%==1 ( :: true ) ) If %x%==0 ( If %y%==0 ( :: False ) )
我只是想,如果我的头顶部。 我可以压缩更多。
我意识到这个问题是旧的,但我想发布一个备用的解决scheme,以防其他人(如我)发现这个线程,而同样的问题。 通过回显variables并使用findstr来validation,我能够解决缺lessOR操作符的问题。
for /f %%v in ('echo %var% ^| findstr /x /c:"1" /c:"2"') do ( if %errorlevel% equ 0 echo true )
虽然dbenham的回答非常好,但如果你正在检查的variables不是一个环境variables,那么依靠IF DEFINED
可能会给你带来麻烦。 脚本variables没有得到这个特殊的处理。
虽然这可能看起来像一些荒谬的无证BS,做一个简单的IF
与IF /?
shell查询IF /?
显示,
DEFINED条件与EXIST类似,只是它需要一个环境variables名称,如果定义了环境variables,则返回true。
关于回答这个问题,是否有理由在一系列的评估之后不要使用简单的标志呢? 这似乎是最灵活的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 /什么goto h:其他xcopy c:current / files g:bu / current有修饰符/ a等等不知道哪一个。 笔记本电脑在店里 和电脑在办公室。 我不在。
从来没有batch file在Windows XP上运行
意识到这是一个古老的问题,答案帮助我想出了一个解决scheme来testingbatch file的命令行参数; 所以我想发布我的解决scheme,以防其他人正在寻找类似的解决scheme。
首先我要指出的是,我无法使IF … ELSE语句在FOR … DO子句中工作。 结果(感谢dbenham在他的例子中不经意地指出了这个),ELSE语句不能与最后一列分开。
所以,而不是这个:
FOR ... DO ( IF ... ( ) ELSE ( ) )
哪一个是我的偏好可读性和美学原因,你必须这样做:
FOR ... DO ( IF ... ( ) ELSE ( ) )
现在,ELSE语句不会作为无法识别的命令返回。
最后,这是我正在试图做的 – 我想能够传递几个参数到任何顺序的batch file,忽略大小写,并报告/未通过传入未定义的参数。所以这里是我的解决scheme…
@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
请注意,这只会报告第一个失败的参数。 所以,如果用户通过一个以上的不可接受的论点,他们将只被告知第一个,直到它被纠正,然后第二个等。