DOS批处理中的逻辑运算符(&;and&;, &;or"

如何在DOS批处理文件中实现逻辑操作符?

542849 次浏览
IF语句不支持逻辑运算符ANDOR。 级联IF语句构成隐式连词:

IF Exist File1.Dat IF Exist File2.Dat GOTO FILE12_EXIST_LABEL

如果File1.Dat 而且 File2.Dat存在,则跳转到标签FILE12_EXIST_LABEL

参见:IF /?

你可以用嵌套条件执行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
)

注意,这个答案是针对Windows中的cmd批处理语言定制的。你提到“DOS批量”;但是,基于以下几点,我认为前一种选择是安全的。

如果你的真的是指最初的MS-DOS批处理语言,你应该记住if语句要简单得多,并且你可能需要使用if ... goto的块来控制流,而不是(例如)括号或else


(1)支持:

  • cmdwindows-console标记的存在;
  • 以前的经验,有些人没有认识到cmd和MS-DOS批处理语言之间的真正区别,并将DOC与cmd终端窗口混为一谈;
  • 使用更通用的“DOS"而不是具体的“MS-DOS"(“DOS"可能是任何磁盘操作系统;
  • 事实上,这是Stack Overflow而不是回溯计算姐妹网站,一个关于MS-DOS的问题会更合适(我也经常在那个网站上,这对我们这些记得并欣赏计算机历史的人来说很好);而且
  • 最初的提问者(最终)接受了答案,表明解决方案有效。

另一种选择是寻找unix shell,它可以提供逻辑操作符和更多的功能。如果你不想走cygwin路线,你可以得到Bourne shell 在这里的本机win32实现。本地bash可以在在这里中找到。我很确定你可以很容易谷歌其他好的替代品,如zsh或tcsh。

K

下面的例子展示了如何创建AND语句(用于为命令设置变量或包含参数)。

启动记事本并关闭CMD窗口:

start notepad.exe & exit

如果变量'a' = blah,则设置变量x、y和z的值。

IF "%a%"=="blah" (set x=1) & (set y=2) & (set z=3)

希望有帮助!

德摩根定律允许我们仅使用连词(“AND”)和否定(“NOT”)将析取(“OR”)转换为逻辑等价。这意味着我们可以将析取(“OR”)链到一行上。

这意味着如果名字是“Yakko”或“Wakko”或“Dot”,那么就呼应“Warner兄弟或姐妹”。

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的反义词是gtrgeq的反义词是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

试试否定操作数“not”!

好吧,如果你可以使用嵌套的“if”对if语句执行“AND”操作(参考前面的答案),那么你可以对“if not”做同样的事情来执行“or”操作。

如果你还没有完全明白,继续往下读。否则,就不要浪费时间,回到编程中去。

就像嵌套的“if”只有在所有条件为真时才被满足一样,嵌套的“if not”只有在所有条件为假时才被满足。这类似于你想要对'or'操作数做的事情,不是吗?

即使嵌套的“if not”中的任何一个条件为真,整个语句仍然不满足。因此,你可以连续使用否定的“if”,记住条件语句的主体应该是你想要做的,如果所有嵌套的条件都是假的。你真正想要给出的主体应该在else语句下。

如果你还是不明白事情的真相,对不起,我16岁了,我只能解释这么多了。

Athul Prakash(当时16岁)给出了如何实现OR测试的逻辑想法,即在IF语句中否定条件,然后使用ELSE子句作为放置需要执行的代码的位置。我对自己说,然而,通常需要两个else子句,因为他建议使用两个IF语句,因此执行的代码需要编写两次。然而,如果GOTO被用来跳过所需的代码,而不是编写ELSE子句,执行的代码只需要编写一次

这是一个可测试的例子,我将如何实现Athul Prakash的负逻辑来创建

在我的例子中,如果有坦克执照或者正在服兵役,就可以开坦克。在两个提示符处输入真正的,你将能够看到逻辑是否允许你驾驶坦克。

@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

这就像下面这样简单:

>如果+如果

if "%VAR1%"=="VALUE" if "%VAR2%"=="VALUE" *do something*

OR> if // if

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*

我知道还有其他的答案,但我认为我的答案更简单,所以更容易理解。希望这对你有所帮助!;)

如果你有兴趣在一个语句中编写if+AND/OR,那么它没有任何一个。但是,你仍然可以将if&&/||(/)语句组合在一起,在一行中实现你想要的,没有任何额外变量,并且没有if-else块复制(AND0和AND1代码部分的单个echo命令):

@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,从而处理到下一个命令的方法。

对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

只有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)