【问题标题】:cmd.exe: complex conditions?cmd.exe:复杂的条件?
【发布时间】:2011-02-15 20:42:06
【问题描述】:

在 DOS 批处理文件中,在 IF 语句中,是否可以使用 AND 或 OR 组合两个或多个条件?我找不到任何相关文档

编辑 - help if 和 MS 文档没有说明在 if 中使用多个条件。

我想 AND 的解决方法是这样做

if COND1 (
  if COND2 (
    cmd
  )
)

但这正是我想要避免的。

【问题讨论】:

  • 当您输入HELP IF 时,您看到了什么?有什么好用的吗?请阅读HELP IF,然后根据您阅读的内容更新您的问题以更具体。

标签: windows batch-file conditional


【解决方案1】:

不,没有更简单的方法。

对于and,您也可以将它们链接起来而不引入块:

if COND1 if COND2 ...

坦率地说,这并不比

if COND1 and COND2 ...

然而,对于or,它确实变得更丑了:

set COND=
if COND1 set COND=1
if COND2 set COND=1
if defined COND ...

或:

if COND1 goto :meh
if COND2 goto :meh
goto :meh2
:meh
...
:meh2

我曾经看到一个批处理预处理器,它使用类似 C 的语法来处理控制流和批处理内容,然后将这些条件转换为多个跳转和检查。但是,那是 DOS 批处理文件,在 Windows 环境中几乎没有用处。

【讨论】:

  • 好一个...如果条件集较短,可以将它们合并为一个,例如:if COND1 set COND=1 else if COND1 set COND=1
  • 是的,但这仅适用于 AND 条件。
【解决方案2】:

我有时想知道,现在人们在学校学到什么!当然“或”也是可能的。任何可以为您提供“NOT”和“AND”的系统也会自动为您提供“OR”,因为:

x OR y = NOT ( (NOT x) AND (NOT y) )http://en.wikipedia.org/wiki/De_Morgan%27s_laws

所以只要表达式“if (x AND y) then do z”可以这样写:

if (x) if (y) (do z)

...我们应该可以写成“if (x OR y) then do z”,但是有一个问题:

我们应该把第一个'NOT'放在哪里?好吧,答案无处可去,我们应该先将上面的等式改写为:

NOT (x OR y) = (NOT x) AND (NOT y)

据此,我们可以将“if (NOT(x OR y)) then (do z)”写成:

"if ((NOT x) AND (NOT y)) then (do z)"

有了这个并且知道如何表达如上所示的AND,我们现在可以将表达式“if (NOT(x OR y)) then (do z)”写成:

if (not x) if (not y) (REM do z)

我们也知道表达式:

"if (NOT p) then (do q) else (do r)"

... 等价于:

"if (p) then (do r) else (do q)

因此我们可以写成“if (x OR y) then (do z)”:

"if (NOT(x OR y)) then (do nothing) else (do z)"

所以我们可以将 "if (x OR y) then (do z)" 表示为:

if (not x) if (not y) (REM do nothing) else (REM do z)

但这还不完整,因为这不是真正的“与”,而是“模拟”的。缺少的是第二个。所以得到正确结果的完整形式应该是:

if (not x) ( if (not y) (REM do nothing) else (REM do z) ) else (REM do z) )

... 它有丑陋的双重 else 部分。您可以使用“goto”来解决这个问题,我们终于拥有了:

rem if (x OR y) then (do z):
if (not x) ( if (not y) (goto :doNothing) )
rem do z
:doNothing

【讨论】:

    【解决方案3】:

    对于我同意乔伊的 AND 解决方法,我看不到其他解决方案。

    对于 OR 解决方法,我会提出以下“技巧”:
    假设您想测试用户在调用批处理文件时是否在命令行上寻求帮助,例如:thebatch /?
    但是您不知道用户是否会输入 /? 或者更确切地说(作为 Unix 习惯用户)--help-h,甚至根本忘记传递任何参数。

    你的代码可能是这样的:

    for %%P in ("" "-h" "--help") do if "%1"==%%P (
       :help
       echo this is my help...  >&2
       exit /b 9
    )
    

    但请注意,测试“/?”要么 ”-?”字符串不适用于该技巧(FOR 循环不喜欢 ? 元字符)。
    为此,只需在块顶部添加以下行:if "%1"=="/?" goto help(参见':help' 标签for循环?)

    还要注意,这种语法对于 TCC.EXE(Take Command 解释器,完整版或精简版)下的批处理文件不起作用(它只是被完全忽略并且代码不会被执行),但在这种情况下,只需将它们的语法与 .OR..AND. 关键字一起使用。

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      如果您的条件是检查变量的特定值,您可以像 CASE 语句一样设置它。我需要检查 TYPE 是单个成员还是组(或全部)

      注意:标签不区分大小写。

      如果任何条件为真(如果TYPE==ALLTYPE==GROUP1TYPE==GROUP2,则执行代码块,否则执行跳过该块。

      goto :TYPE_EQ_%TYPE% 2>NUL
      if %ERRORLEVEL% neq 0 goto :END_CASE_TYPE
      :TYPE_EQ_ALL
      :TYPE_EQ_GROUP1
      :TYPE_EQ_GROUP2
      rem do what you need
         echo GROUP: %TYPE%
      :END_CASE_TYPE
      

      我不喜欢 Mehrdad 的电气工程(数字电子) 方法。虽然准确,但对于软件工程来说,正如 OP 所指出的那样,这个想法是让事情变得更容易弄清楚。嵌套的 if 语句增加了复杂性 (McCabe)。添加额外的 NOT 没有帮助。

      如果您不知道 goto-label/error 设置,我的解决方案会有点奇怪,但它是一个扁平结构,大致设置为带有多个 OR 条件的 if 语句很难破译。

      【讨论】:

        【解决方案5】:

        与:

        IF <COND1> IF <COND2> ACTION
        

        或者:

        (SET _=) & (IF <COND1> (SET _= ) ELSE IF <COND2> (SET _= )) & IF DEFINED _ ACTION
        

        要以这种方式实现 OR,您确实需要命令扩展。

        【讨论】:

          【解决方案6】:

          只要启用命令扩展,就可以使用比较运算符。

          这是直接从“help if”粘贴的:

          如果启用命令扩展 IF 更改如下:

          IF [/I] string1 compare-op string2 command
          IF CMDEXTVERSION number command
          IF DEFINED variable command
          

          compare-op 可能是以下之一:

          EQU - equal
          NEQ - not equal
          LSS - less than
          LEQ - less than or equal
          GTR - greater than
          GEQ - greater than or equal
          

          如果指定了 /I 开关,则表示执行不区分大小写的字符串 比较。 /I 开关也可用于 string1==string2 形式 中频的。这些比较是通用的,如果 string1 和 string2 都由所有数字组成,那么字符串是 转换为数字并进行数字比较。

          【讨论】:

          • 那么,OP 询问的逻辑 andor 在哪里?问题不在于简单的比较条件。
          • @Johannes Rössel:哦,对不起,我的错。我需要更仔细地阅读。
          • -1 -- 再多一个,你就可以获得一个 Peer Pressure 徽章 ;-)
          猜你喜欢
          • 2013-01-31
          • 1970-01-01
          • 2018-07-28
          • 1970-01-01
          • 1970-01-01
          • 2019-03-09
          • 1970-01-01
          • 2014-06-22
          • 2017-07-27
          相关资源
          最近更新 更多