【发布时间】:2011-01-09 17:37:42
【问题描述】:
如何在 DOS 批处理文件中实现逻辑运算符?
【问题讨论】:
-
我提交给您观看乐趣:pi.bat :) thedailywtf.com/Articles/…
标签: batch-file cmd logical-operators windows-console
如何在 DOS 批处理文件中实现逻辑运算符?
【问题讨论】:
标签: batch-file cmd logical-operators windows-console
你可以用嵌套条件做and:
if %age% geq 2 (
if %age% leq 12 (
set class=child
)
)
或:
if %age% geq 2 if %age% leq 12 set class=child
你可以用一个单独的变量来做or:
set res=F
if %hour% leq 6 set res=T
if %hour% geq 22 set res=T
if "%res%"=="T" (
set state=asleep
)
【讨论】:
set res= 或set res=1,然后使用if defined res,这对拼写错误更加稳健,即使在没有明确启用延迟扩展的情况下也可以在块中使用。
IF 语句不支持逻辑运算符AND 和OR。
级联 IF 语句构成一个隐式连接:
IF Exist File1.Dat IF Exist File2.Dat GOTO FILE12_EXIST_LABEL
如果File1.Dat 和 File2.Dat 存在则跳转到标签FILE12_EXIST_LABEL。
另请参阅:IF /?
【讨论】:
De Morgan's laws 允许我们仅使用连词(“AND”)和否定(“NOT”)将析取(“OR”)转换为逻辑等价物。这意味着我们可以将析取(“OR”)链接到一行。
这意味着如果名字是“Yakko”或“Wakko”或“Dot”,则回显“Warner Brother or Sister”。
set warner=true
if not "%name%"=="Yakko" if not "%name%"=="Wakko" if not "%name%"=="Dot" set warner=false
if "%warner%"=="true" echo Warner brother or sister
这是 paxdiablo 的“OR”示例的另一个版本,但条件被链接到一行。 (注意leq的反义词是gtr,geq的反义词是lss。)
set res=true
if %hour% gtr 6 if %hour% lss 22 set res=false
if "%res%"=="true" set state=asleep
【讨论】:
OR 有点棘手,但并不过分。这是一个例子
set var1=%~1
set var2=%~2
::
set or_=
if "%var1%"=="Stack" set or_=true
if "%var2%"=="Overflow" set or_=true
if defined or_ echo Stack OR Overflow
【讨论】:
以下示例展示了如何创建 AND 语句(用于设置变量或包含命令的参数)。
启动记事本并关闭 CMD 窗口:
start notepad.exe & exit
如果变量 'a' 等于 blah,则将变量 x、y 和 z 设置为值。
IF "%a%"=="blah" (set x=1) & (set y=2) & (set z=3)
希望有帮助!
【讨论】:
如果你有兴趣在一个语句中写一个if+AND/OR,那么没有任何一个。但是,您仍然可以将if 与&&/|| 和(/) 语句组合在一起,以在一行中实现您想要的不带任何其他变量和不带if-else 块重复(单个echo 命令用于TRUE 和FALSE 代码部分):
@echo off
setlocal
set "A=1" & set "B=2" & call :IF_AND
set "A=1" & set "B=3" & call :IF_AND
set "A=2" & set "B=2" & call :IF_AND
set "A=2" & set "B=3" & call :IF_AND
echo.
set "A=1" & set "B=2" & call :IF_OR
set "A=1" & set "B=3" & call :IF_OR
set "A=2" & set "B=2" & call :IF_OR
set "A=2" & set "B=3" & call :IF_OR
exit /b 0
:IF_OR
( ( if %A% EQU 1 ( type nul>nul ) else type 2>nul ) || ( if %B% EQU 2 ( type nul>nul ) else type 2>nul ) || ( echo.FALSE-& type 2>nul ) ) && echo TRUE+
exit /b 0
:IF_AND
( ( if %A% EQU 1 ( type nul>nul ) else type 2>nul ) && ( if %B% EQU 2 ( type nul>nul ) else type 2>nul ) && echo.TRUE+ ) || echo.FALSE-
exit /b 0
更统一的版本:
@echo off
setlocal
set "A=1" & set "B=2" & ( call :IF_AND "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
set "A=1" & set "B=3" & ( call :IF_AND "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
set "A=2" & set "B=2" & ( call :IF_AND "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
set "A=2" & set "B=3" & ( call :IF_AND "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
echo.
set "A=1" & set "B=2" & ( call :IF_OR "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
set "A=1" & set "B=3" & ( call :IF_OR "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
set "A=2" & set "B=2" & ( call :IF_OR "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
set "A=2" & set "B=3" & ( call :IF_OR "%%A%% EQU 1" "%%B%% EQU 2" && echo TRUE+ ) || echo FALSE-
exit /b 0
:IF_OR
if %~1 ( exit /b 0 ) else if %~2 ( exit /b 0 ) else exit /b 1
exit /b -1
:IF_AND
if %~1 ( if %~2 ( exit /b 0 ) else exit /b 1 ) else exit /b 1
exit /b -1
输出:
TRUE+
FALSE-
FALSE-
FALSE-
TRUE+
TRUE+
TRUE+
FALSE-
诀窍在于type 命令,它删除/设置errorlevel 并因此处理下一个命令的方式。
【讨论】:
if %A% EQU 1, if %B% EQU 2,其中:IF_OR 分别代表if %A% EQU 1 或if %B% EQU 2。
Athul Prakash(当时 16 岁)通过否定 IF 语句中的条件,然后使用 ELSE 子句作为放置需要执行的代码的位置,就如何实现 OR 测试给出了一个合乎逻辑的想法。我心想,通常需要两个 else 子句,因为他建议使用两个 IF 语句,因此执行的代码需要编写 两次。但是,如果使用 GOTO 跳过所需的代码,则无需编写 ELSE 子句,只需编写执行代码一次。
这是一个可测试的示例,说明我将如何实现 Athul Prakash 的否定逻辑来创建 OR。
在我的示例中,持有坦克执照或正在服兵役的人可以驾驶坦克。在两个提示符处输入true或false,你就能看到逻辑是否允许你开坦克。
@ECHO OFF
@SET /p tanklicence=tanklicence:
@SET /p militaryservice=militaryservice:
IF /I NOT %tanklicence%==true IF /I NOT %militaryservice%==true GOTO done
ECHO I am driving a tank with tanklicence set to %tanklicence% and militaryservice set to %militaryservice%
:done
PAUSE
【讨论】:
就像下面这样简单:
AND> 如果+如果
if "%VAR1%"=="VALUE" if "%VAR2%"=="VALUE" *do something*
OR> 如果 // 如果
set BOTH=0
if "%VAR1%"=="VALUE" if "%VAR2%"=="VALUE" set BOTH=1
if "%BOTH%"=="0" if "%VAR1%"=="VALUE" *do something*
if "%BOTH%"=="0" if "%VAR2%"=="VALUE" *do something*
我知道还有其他答案,但我认为我的更简单,所以更容易理解。希望这对你有帮助! ;)
【讨论】:
尝试否定操作数 - 'not'!
好吧,如果您可以使用嵌套的 'if' 对 if 语句执行 'AND' 操作(请参阅之前的答案),那么您可以使用 'if not' 执行相同的操作来执行 'or' 操作。
如果您还没有完全理解这个想法,请继续阅读。否则,请不要浪费您的时间并重新开始编程。
就像嵌套的 'if' 仅在所有条件都为真时才满足,嵌套的 'if not' 仅在所有条件都为假时才满足。这类似于您想要对“或”操作数执行的操作,不是吗?
即使嵌套的“if not”中的任何一个条件为真,整个语句仍然不满足。因此,您可以通过记住如果所有嵌套条件都为假,条件语句的主体应该是您想要执行的操作,可以连续使用否定的 'if's。你真正想要给出的主体应该在 else 语句下。
如果你还是不明白事情的原委,对不起,我 16 岁,这是我能做的最好的解释。
【讨论】:
【讨论】:
只有 OR 部分比较棘手,但使用包含 NOT OR AND 的通用布尔表达式,唯一不错的解决方案是:
REM if A == B OR C == C then yes
(call :strequ A B || call :strequ C C) && echo yes
exit /b
:strequ
if "%1" == "%2" exit /b 0
exit /b 1
【讨论】:
很多人似乎错过了 OR 最明显的解决方案,即使用标签。
if "%a%" == "ONE" goto do_thing
if "%a%" == "TWO" (
:do_thing
echo a is equal to ONE or TWO
)
【讨论】:
如果您需要 else 子句,则可以使用以下语法:
与:
if %v1% == a (if %v2% == b (echo yes) else echo no) else echo no
或者:
if %v1% == a (echo yes) else (if %v2% == b (echo yes) else echo no)
【讨论】:
对 Andry 的回答稍作修改,减少重复的类型命令:
set "A=1" & set "B=2" & call :IF_AND
set "A=1" & set "B=3" & call :IF_AND
set "A=2" & set "B=2" & call :IF_AND
set "A=2" & set "B=3" & call :IF_AND
echo.
set "A=1" & set "B=2" & call :IF_OR
set "A=1" & set "B=3" & call :IF_OR
set "A=2" & set "B=2" & call :IF_OR
set "A=2" & set "B=3" & call :IF_OR
goto :eof
:IF_OR
(if /i not %A% EQU 1 (
if /i not %B% EQU 2 (
echo FALSE-
type 2>nul
)
)) && echo TRUE+
goto :eof
:IF_AND
(if /i %A% EQU 1 (
if /i %B% EQU 2 (
echo TRUE+
type 2>nul
)
)) && echo FALSE-
goto :eof
【讨论】:
if /i ... 或if not ... 仅对字符串比较有意义:if /i "aaa" == "AAA" ...。 if a EQU b 是数字比较,您必须使用 if a NEQ b 进行数字不相等比较。 2.批处理文件中的多行语句基本上比单行慢,因为每行在解析时都从脚本文件中重新读取。 3.例如,如果IF_OR第一个条件为真,第二个条件为假,那么真正的代码块不会调用。