逻辑判断

逻辑判断(Logical Judgement),是指使用 if 指令或者其它判断指令进行判断并控制流程进行的一种方式,它是程序的重要组成部分。在 Batch 中,我们大部分时间都会选择使用 if,此外还有逻辑判断符号 || 和 && 存在。

if

if 可以判断变量与值、变量与变量、值与值的关系,基本语法如下

set a=1
:: 如果 a 等于 1
if "%a%"=="1" ( 
    echo Variable a equals to 1. 
) else (
    echo Variable a doesn't equal to 1.
)

其中,if 语句所使用的代码块需要使用 () 括起来,而不是像其它语言那样的 {}。另外,Batch 内没有 else if 的用法,因此,如果您想要使用 else if,那么您可能需要这样写:

set a=1
:: 如果 a 等于 1
if "%a%"=="1" ( 
    echo Variable a equals to 1. 
) else  (
    :: 如果 a 等于 2
    if "%a%" == "2" (
        echo Variable a doesn't equal to 1 but 2.
    ) else (
        echo Variable a doesn't equal to 1 or 2.
    )
)

也就是说,您必须在 else 后的代码块里写 if 而不是直接紧跟在后面写 if

当您初次看见这个判断语法时,可能认为很荒谬。为什么没有括号?就像其它语言那样:

// PHP
class GetContent {
    public function init()
    {
       if ($_GET["p"] == 1)
        {
            return 2;
        } else if ($_GET["p"] != 2) {
            return $_GET["p"];
        }
    }
}

$GetContent = new GetContent();
$p = $GetContent->init();

这是 Batch 的个性。如果您先前对 if 语句没有丝毫的了解,可以看一下下面这个奇妙的公式:

:: 如果 对比因素 对比条件 对比因素
if 对比因素+对比条件+对比因素 (
    成立操作
) else (
    不成立操作
)

例如,我们要判断 1 是否等于 2,我们就可以这样写:

if "1" == "2" (
    echo 很抱歉,当您看到这条消息的时候,说明您已经没有生活在人类文明内了。
) else (
    echo Hello World!
)
pause
exit

其中 else 语句可要可不要,如果不需要,则会出现两种写法:

:: 如果 1 等于 2
if "1" == "2" (
    echo 很抱歉,当您看到这条消息的时候,说明您已经没有生活在人类文明内了。
)

:: 或者

:: 如果 1 等于 2
if "1" == "2" echo 很抱歉,当您看到这条消息的时候,说明您已经没有生活在人类文明内了。

如果您是缩进爱好者,可以选择前者。后者可以让您的代码在单行中看起来更简洁,但是后者不能用 else

if not

与其它语言相似,Batch 也有判断非的方式,只不过并不是用的 != 而是更直接了当的 if not,它的用法与 if 没有区别,只是对结果取反而已。

:: 如果 1 不等于 1
if not "1" == "1" echo 很抱歉,当您看到这条消息的时候,说明您已经没有生活在人类文明内了。

if / not defined

if not defined 和 if defined 用于测试一个变量是否被定义,if not defined 的成立条件是没有定义,if defined 的成立条件是已经定义。在 if not defined () 后面加上 else 就相当于是 if defined 了,原理很好理解。

用法:

:: 如果 变量名 没有被定义
if not defined 变量名 (
    成立操作
) else (
    不成立操作
)

:: 当然也可以简化写成单行

if not defined 变量名 成立操作

实例:


:: 如果不存在 a 这个变量,那么
if not defined a (
    set a=1
) else (
    echo %a%
    pause
    exit
)

if defined 则相反。

当然,我们也可以用 if 来实现 if not defined 的效果:

:: 如果一个变量的值是空的,我们大概就可以说它没有被定义。
if "%变量名%"=="" 成立操作

也就是说 if "%变量名%"=="" 相当于 if not defined 变量名。但是大多数情况下,我们建议选取后者使用,因为这样更加规范,前者不知道会不会有 Bug。

if / not exist

if exist 和 if not exist 也是相反的一对判断。它们判断某文件是否存在。用法:

:: 如果存在某文件
if exist 文件路径 成立操作
:: 如果不存在某文件
if not exist 文件路径 成立操作

它们也可以使用 else

if 的数字判断

与 set 一样,if 也有专用于数字的用法。我们可以比大小。以下是一个简单的比较大小程序:

set /p a=请输入 a:
set /p b=请输入 b:
:: 如果 a 的值比 b 的值大
if %a% gtr %b% (
    echo %a%%b% 大。
) else (
    echo %a% 小于或等于 %b%。
)

用 if 比较大小的关键在于中间的符号。我们判断两个值相等可以使用 ==,但是必须需要前后两者加上引号。而我们可以直接使用表达数学关系的字母简称来代表数字之间的关系(其它的,诸如字符之类的,不能用,只能用 ==)。

以下是 Batch 中判断数字关系的字母简称:

字母简称 英文全称 含义
equ Equal 相等
gtr Greater 大于
geq Greater or Equal 大于或等于
lss Less 小于
leq Less or Equal 小于或等于
neq Not Equal 不等

我们就可以用非负性原理来判断数值之间的关系:

set /p a=请输入 a:
set /p b=请输入 b:
if %a% geq %b% (
    if %a% leq %b% (
        echo a = b
    ) else (
        echo a != b
    )
) else (
    if %a% geq %b% (
        echo a = b
    ) else (
        echo a != b
    )
)

:: 无法理解是很正常的,您可以学完了以后再回来看。

if %ERRORLEVEL%

%ERRORLEVEL% 是一个环境变量,它在不同的指令执行后会有不同的值。以下列出一些特殊情况的 %ERRORLEVEL% 值。

ERRORLEVEL 值 含义 执行指令示例
0 执行成功 / 一切正常 echo 111(这个指令是没有理由失败的)
1 目录不存在 / 进程占用 cd con(您不可能在 Windows 下创建一个名为 connul 等的目录)
5 权限不足 nul(无论如何执行 nul 指令都会提示无权限,包括在管理员模式下)
32 正在操作当前目录 缺省
145 目录非空 rd %Systemdrive%\Windows(这个目录空了您就没机会执行这个指令了)
1073750991 语法错误 set /a a=1+two(一般语法错误会直接在回显中提示出来)
9009 不存在的指令 hellobrothisisacommanddoyoubelieveit?!
exitCode 由 exit /b 的 exitCode 决定 exit /b 233,此时 %ERRORLEVEL%等于 233。

注意: ERRORLEVEL 是一个非常奇妙的东西,在有些时候它甚至可以等于任何值,没人知道它到底能等于多少。上表列出来的只是一些常见的、较为稳定的错误代码。ERRORLEVEL 一般不会等于 32。

如果我们要判断 ERRORLEVEL,我们直接使用数学判断语句即可:

if %ERRORLEVEL% neq 0 echo 有错误出现
:: 只要 ERRORLEVEL 不是 0 就代表上个指令有问题。

我们可以使用前面提到过的 exit /b 和 if %ERRORLEVEL% 来完成程序之间的传参工作,这将在“调用与参数”中讲到。

逻辑判断符

Batch 的逻辑判断符(Logical Judge)分为两种:|| 与 &&,它们并不是如三元运算符(Ternary Operator)一样发挥着 if else 的作用,而是用来判断指令是否执行成功。

它的用法是直接接在需要判断的指令后面:

指令 逻辑判断符 成立操作

例如,我们要判断 echo 指令是否成功,我们有两种写法:

echo 1 || echo 不成功
echo 1 && echo 成功

|| 代表,若前面的指令不成功,则执行后面的指令,&& 相反,若前面的执行成功,则执行后面的指令。它们可以连用,但是如果混用着连用,很容易产生奇怪的 Bug,因此笔者不建议连用。

我们可以使用逻辑判断符完成很多工作,例如,我们判断用户的输入是否为数字,来提前避免处理过程中出现不必要的问题。

set /p a=请输入需要判断的字符(串):
set b=1
@set /a c=b+1a || echo %a% 不是数字。
pause
exit

如果 a 不是数字,@set /a c=b+1a 就会出现问题,于是就会被 || 检测到,随即执行后面的指令。不过,为什么不写成 set /a c=b+a 呢?因为如果单纯地将一个非数字的变量写入表达式中,会被直接看作是 0,当再加上一个数字的时候,就相当于想要把 1a 这个数字字母组合看成数字,这是不可能的,于是自然会失败。

至于为什么要添加 @,这是为了避免回显的失败信息。因为一个指令执行失败后必定会有失败信息,而我们正是在取代失败信息,因此我们不需要系统的失败信息。当然如果您需要可以把 @ 去掉。