有没有办法在Windows批处理文件中写入IF或IF条件语句?
例如:
IF [%var%] == [1] OR IF [%var%] == [2] ECHO TRUE
Answers:
zmbq解决方案很好,但是不能在所有情况下都使用,例如在FOR FOR(...)循环之类的代码块内。
另一种方法是使用指标变量。将其初始化为未定义,然后仅在任何一个OR条件为true时定义它。然后使用IF DEFINED作为最终测试-无需使用延迟扩展。
FOR ..... DO (
set "TRUE="
IF cond1 set TRUE=1
IF cond2 set TRUE=1
IF defined TRUE (
...
) else (
...
)
)
您可以添加arasmussen使用的ELSE IF逻辑,理由是如果第一个条件为true,它可能会更快执行,但我从不打扰。
附录 -这是一个重复的问题,与在IF语句中使用OR的答案几乎完全相同 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)
)
根据VAR中的期望值,可能需要诸如“ delims =”之类的FOR选项
=
通过添加更多代码,即使在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%
还包含空格或特殊字符(如等)^
,则引号会导致问题&
。此解决方案的另一个限制是,除非您添加指示符变量,否则它不提供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
ECHO Didn't find it
即使找到它,您也将击中它。
感谢这篇文章,它对我有很大帮助。
Dunno如果可以解决问题,但我遇到了问题,感谢您,我发现我认为这是基于布尔等价物的另一种解决方法:
“ A或B”与“不是(不是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而是执行“ inplace”操作,则可以执行3次该操作。
没有IF <arg> OR
或ELIF
或ELSE IF
批处理,但是...
尝试将其他IF嵌套在上一个IF的ELSE内。
IF <arg> (
....
) ELSE (
IF <arg> (
......
) ELSE (
IF <arg> (
....
) ELSE (
)
)
可以使用一个函数,该函数对“或”逻辑求值并返回单个值。
@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 ...
语句。
可以通过间接使用IF来实现此目标。
下面是一个复杂表达式的示例,可以在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
尽管dbenham的答案相当不错,但是IF DEFINED
如果要检查的变量不是环境,依靠它可能会给您带来麻烦变量。脚本变量没有得到特殊处理。
尽管这看起来像是一些可笑的未记录的BS,但通过对IF
with 进行简单的shell查询可以IF /?
发现,
DEFINED条件条件的工作方式类似于EXIST,不同之处在于它采用 环境变量名称,并且如果定义了环境变量,则返回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 /转到h:其他xcopy c:current / files g:bu / current有修饰符/ 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语句不能与结尾处分开。
所以代替这个:
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
。