【问题标题】:Logical operators ("and", "or") in DOS batchDOS批处理中的逻辑运算符(“and”、“or”)
【发布时间】:2011-01-09 17:37:42
【问题描述】:

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

【问题讨论】:

标签: batch-file cmd logical-operators windows-console


【解决方案1】:

你可以用嵌套条件做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”语句...您可以将它们“链接”起来,如下面的 Dave Jarvis 所示
  • 注意不要在 set=true 之后留下任何空格,否则就不能正常工作。它将值“true”存储在变量中......
  • 您描述的“或”条件很巧妙,适用于一系列数字,但是如果我比较 2 个独立值而不是一个范围怎么办?例如,如果此文件存在或 filename == ""
  • @bakoyaro,您可以使用任何条件将 res 设置为 true,包括您提到的那些。
【解决方案2】:

IF 语句不支持逻辑运算符ANDOR。 级联 IF 语句构成一个隐式连接:

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

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

另请参阅:IF /?

【讨论】:

    【解决方案3】:

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

    set res=true
    if %hour% gtr 6 if %hour% lss 22 set res=false
    if "%res%"=="true" set state=asleep
    

    【讨论】:

      【解决方案4】:

      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
      

      【讨论】:

      • 不起作用。如果我给它堆栈,它会回声。如果我给它溢出,它不会 - 它应该。
      【解决方案5】:

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

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

      start notepad.exe & exit
      

      如果变量 'a' 等于 blah,则将变量 x、y 和 z 设置为值。

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

      希望有帮助!

      【讨论】:

        【解决方案6】:

        如果你有兴趣在一个语句中写一个if+AND/OR,那么没有任何一个。但是,您仍然可以将if&&/||(/) 语句组合在一起,以在一行中实现您想要的不带任何其他变量和不带if-else 块重复(单个echo 命令用于TRUEFALSE 代码部分):

        @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 并因此处理下一个命令的方式。

        【讨论】:

        • 这里检查的实际情况是什么?这很难说。
        • @Unknow0059 if %A% EQU 1, if %B% EQU 2,其中:IF_OR 分别代表if %A% EQU 1if %B% EQU 2
        【解决方案7】:

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

        这是一个可测试的示例,说明我将如何实现 Athul Prakash 的否定逻辑来创建 OR

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

        @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
        

        【讨论】:

          【解决方案8】:

          就像下面这样简单:

          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*
          

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

          【讨论】:

            【解决方案9】:

            尝试否定操作数 - 'not'!

            好吧,如果您可以使用嵌套的 'if' 对 if 语句执行 'AND' 操作(请参阅之前的答案),那么您可以使用 'if not' 执行相同的操作来执行 'or' 操作。

            如果您还没有完全理解这个想法,请继续阅读。否则,请不要浪费您的时间并重新开始编程。

            就像嵌套的 'if' 仅在所有条件都为真时才满足,嵌套的 'if not' 仅在所有条件都为假时才满足。这类似于您想要对“或”操作数执行的操作,不是吗?

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

            如果你还是不明白事情的原委,对不起,我 16 岁,这是我能做的最好的解释。

            【讨论】:

            • x=2 或 x=3 => ! ! (x=2 或 x=3) => ! (x != 2 and x !=3) 我认为你不能否定整个 if 结构来应用必要的外部“非”运算符。已经 3 年了,@Athul-prakash,有什么想法吗?
            【解决方案10】:

            另一种方法是寻找一个确实为您提供逻辑运算符和更多功能的 unix shell。如果您不想走 cygwin 路线,您可以获得 Bourne shell here 的本机 win32 实现。可以在 here 找到本机 bash。我很确定您可以轻松地在 Google 上搜索其他不错的替代品,例如 zsh 或 tcsh。

            K

            【讨论】:

            • 如果您打算使用不同的 shell,至少要使用 PowerShell:microsoft.com/powershell
            • 有很多比 DOS 更好的 shell。我之所以使用 DOS bat 文件是因为它不需要任何外部工具。如果您的客户需要自动化一些简单的事情,您真的希望他们必须安装特殊工具(cygwin、perl、powershell 等),而 BAT 文件就足够了吗?
            • BAT 在大多数情况下就足够了。 ppl 编写的 90% 的 unix shell 脚本不是纯 shell,而是带有许多 coreutils、sed、awk 等调用。 GNU 已经在其他操作系统中实现了 UNIX 好东西,包括 Windows。所以看看这个getgnuwin32.sourceforge.net cmd.exe/bash/zsh 加上这对大多数任务来说应该足够了。如果你有 BAT/UNIX Shell 经验,就没有理由学习所谓的 PowerShell
            【解决方案11】:

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

            【讨论】:

              【解决方案12】:

              很多人似乎错过了 OR 最明显的解决方案,即使用标签。

              if "%a%" == "ONE" goto do_thing
              if "%a%" == "TWO" (
                 :do_thing
                 echo a is equal to ONE or TWO
              )
              

              【讨论】:

                【解决方案13】:

                如果您需要 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)
                

                【讨论】:

                  【解决方案14】:

                  对 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
                  

                  【讨论】:

                  • 一些细节:1.if /i ...if not ... 仅对字符串比较有意义:if /i "aaa" == "AAA" ...if a EQU b 是数字比较,您必须使用 if a NEQ b 进行数字不相等比较。 2.批处理文件中的多行语句基本上比单行慢,因为每行在解析时都从脚本文件中重新读取。 3.例如,如果IF_OR第一个条件为真,第二个条件为假,那么真正的代码块不会调用。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-01-31
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多