Board logo

标题: [原创] [专题教程]批处理if命令的基本用法 [打印本页]

作者: pusofalse    时间: 2008-10-17 01:41     标题: [专题教程]批处理if命令的基本用法

if在批处理编程中是一个高级命令,熟练掌握if的用法可以大大提高代码的效率、简洁度。此教程将用实例说明if的基本用法。
if--如同它的汉语意思:如果,它的作用就是执行条件判断处理,如果条件成立,则执行后面的命令,反之则不执行。
if语句中的关键字:
if
not(非) else(否则)
==(等于) equ(等于) neq(不等于) lss(小于) leq(小于或等于) gtr(大于) geq(大于或等于)
defined(用于检测一个变量的值是否为空) exist(判断文件(夹)是否存在) errorlevel(判断上一条命令的返回码)

执行if语句,当然的关键字if不能少。
== equ neq lss leq gtr geq 在执行比较运算时,这些比较运算符必须要指定一个。其中的not可有可无,至于为何,看下面的示例。
【example1】
If的简单比较:
  1. if a lss b echo a果真小于b
复制代码
这条命令的意思是:如果字母a小于字母b,则显示“a果真小于b”。lss是小于的意思。
  1. if not a lss b echo a竟然不小于b
复制代码
这条命令的意思是:如果字母a不小于字母b,则显示“a竟然不小于b”
运行之,没有返回任何结果,因为条件不成立,a本来就小于b。
不小于,等效于“大于或等于”,所以上条命令也可写作这样:
  1. if a geq b echo a大于或等于b
复制代码
geq是大于或等于的意思。这就是not可有可无的原因。
如果要比较的两个字符串中有空格呢:
  1. if a lss x y echo a小于x y
复制代码
显示出错。这样因为if所认为的要比较的两个字符串是a与x的比较,错把其后的y当成了是一个命令。
如果一个完整的参数中有空格,需要用双引号"将这个完整的参数闭合。所以正确的应该如下:
  1. if "a" lss "x y" echo a小于x y
复制代码
需要注意的是,比较符左右两边只要有一边加"",另一边也要加""。
如果是字符串(不是纯数字)的比较,最好都用""将其闭合,这是良好的习惯。
【example2】
if 比较字符串与比较数字 之间的区别:
这种区别体现在引号"上面,看下面对数字的比较。
  1. if "12" lss "4" echo 12竟然小于4?
复制代码
运行之,奇怪,12竟然小于4?if的逻辑混乱了吗?当然不是,测试下面的代码:
  1. if 12 lss 4 echo 12竟然小于4?
复制代码
无任何返回结果,当然是因为条件不成立,谁能理直气壮地告诉我12小于4?
那么,从上面的两个测试代码中了解到什么了吗?
如果要比较的两个元素加了"",那么会被当成是字符的比较。这样的比较,它的流程是:
先比较两个元素的首位,如果首位相同,再比较第二位,如果第二位相同,再比较第三位,依此。
所以:if "12" lss "4" echo 12小于4
实质是1与4的比较,1当然小于4,所以执行了后面的命令。
而两个元素都不加"",则会当作是数字的比较,此时与我们的逻辑思维相吻合。
测试以上两代码,得出这个结论:
要比较的两元素如果加了"",会被当作是字符串的比较,不加"",则是数字之间的比较。
如果是个位数之间的比较,加与不加引号""都可行。
上面所说的"12"小于"4"的现象只出现在比较运算符lss、leq、gtr、geq中,equ(等于)或==(等于)、neq(不等于)中并无此“矛盾”现象。

【example3】
以上,都是字符常量之间的比较,变量之间的比较也是一样:
  1. set "var=abc"
  2. if "%var%" equ "abc" echo 变量var已经被定义,它的值是abc
  3. pause
复制代码
以上代码存为test.bat,运行,仔细观察其运行过程、结果
【example4】
if...else...的用法:
else表示否则,如果前面的条件不成立,指定要运行的命令,其用法如下:
  1. set "var1=abc"
  2. set "var2=ABC"
  3. if "%var1%"=="%var2%" (echo var1等于var2) else echo var1不等于var2
  4. pause
复制代码
需注意,用等号作为比较符时,需用两个,连在一起。
在if...else...句式中,条件成立时要执行的命令需用()将命令闭合,条件不成立时,else之后的命令可用()闭合,也可不用。
上面的代码输出“var1不等于var2”,是因为if比较两元素时,默认是区分大小写的,如果指定不区分大小写,用/i参数:
  1. set "var1=abc"
  2. set "var2=ABC"
  3. if /i "%var1%" equ "%var2%" (echo var1等于var2) else (echo var1不等于var2)
  4. pause
复制代码
同样,仔细观察其运行过程
附:
各比较运算符之间的关系:
if "str1"=="str2" command 等效于 if "str1" equ "str2" command
if not "str1"=="str2" command 等效于 if "str1" neq "str2" command 等效于 if not "str1" equ "str2" command
if not "str1" lss "str2" command 等效于 if "str1" geq "str2" command
if "str1" leq "str2" command 等效于 if not "str1" gtr "str2" command
....

【example5】
if defined 用法:
如defined释义一样,它的作用就是检测一个变量是否被定义,所谓定义,即是一个变量已经被赋值。反之未定义,即是空值。
  1. set "var=test"
  2. if defined var (echo 变量var已经被定义,它的值是%var%) else echo var未被赋值。
  3. set "var="
  4. if not defined var (echo var未被赋值。) else (echo 变量var已经被定义,它的值是%var%)
  5. pause
复制代码
需注意,var不能用%%闭合,否则,要检测 是否被定义的是 var的值test。
检测一个变量是否为空可以用如上方法实现,同样,使用比较运算符也可以实现:
if defined var...等效于 if "%var%" neq "" ...
if not defined var...等效于if "%var%"=="" ...

判断变量var是否是空值,空值用""表示。
更多关于if defined的用法及须知,参看随风版主的这篇帖子:
http://bbs.bathome.net/viewthread.php?tid=2050&highlight=if%2Bdefined
【example6】
if exist ...用法:
句式:if exist "文件(夹)名" 要执行的命令
它的作用就是检测指定的文件(夹)是否存在
  1. if not exist c:\windows\ echo c:\windows\ not exists.
  2. rem 如果不存在c:\windows\文件夹,则显示c:\windows not exists.
  3. if exist "c:\program files\a.txt" (
  4.   echo c:\program files\a.txt exists.
  5.   rem 如果存在c:\program files\a.txt,则显示c:\program files\a.txt exists.
  6.   rem 如果c:\program files\中有个文件夹是以a.txt命名的,也会显示c:\program files\a.txt exists.所以,要判断是否存在指定文件夹,路径最后最好要以\结束。
  7.   ) else (
  8.   echo c:\program files\a.txt doesn't exist.
  9.   rem 否则,显示c:\program files\a.txt doesn't exist.
  10. )
  11. pause
复制代码
再次说明一下,如果路径(一个完整的参数)中有空格,要用""将其闭合。
分行写的好处在于:使代码看起来美观,明晰易懂,不至于臃肿。只是要注意分行写的格式。
上面的例子中,if exist在判断是文件还是文件夹的时候并不严谨,那么如何判断指定的文件a.txt是否存在?如下:
  1. dir/a-d a.txt 2>nul
  2. if errorlevel 0 (echo a.txt是文件)
  3. pause
复制代码
以上代码,先用dir的/a参数去除a.txt的目录属性,指定说明要搜索的a.txt是文件而不是文件夹,并把错误结果屏蔽(2>nul),如果dir找到了文件a.txt,那么其errorlevel值(dir命令的退出编码)会被设为0,否则为1则是没有此文件。当然也可以用||和&&来判断,新手们拿来做练习吧。关于if errorlevel的用法,例7中有介绍。
更多关于判断文件还是文件夹的方法,参看namejm站长的这篇帖子:
http://bbs.bathome.net/viewthread.php?tid=1047&highlight=%2Bnamejm

【example7】
if errorlevel ...用法:
if errorlevel 程序返回码(数字) 要执行的命令
它的作用是检测上一条命令的运行结果(运行成功or失败)
每一个命令执行完成都会返回一个退出编码,不同的退出编码代表不同的完成状态,一般来说0为成功。
用个实例来说明:
ping百度,根据ping命令的返回码来检测当前是否已经连接至网络。
  1. @echo off
  2. ping www.baidu.com
  3. if errorlevel 0 (
  4.    echo 网络正常。
  5.    ) else (
  6.    if errorlevel 1 (
  7.       echo 网络异常。
  8.       ) else (
  9.       echo ping被中断。
  10.    )
  11. )
  12. pause
复制代码
if errorlevel 0...等效于if "%errorlevel%" equ "0"...
if not errorlevel 1... 等效于if "%errorlevel%" neq "1"...
一般来说,命令成功会返回0,否则为1或别的数字。由于errorlevel的值不好得知,所以也可以用如下代码判断:
  1. @ping www.baidu.com&&echo 网络正常。||echo 网络异常。
复制代码
要得知程序返回码,最好的办法是上网查询,或者用如下代码:
  1. 命令。。。
  2. echo %errorlevel%
复制代码
在CMD中一条一条输入以上命令,在各种环境下测试以上代码,比如在“命令”运行时被Ctrl+C终止等。
练习:
1、分别判断系统中有无administrator与testif用户,有则显示“有”,无则显示“无”。
2、指出如下代码中的错误并修改:
  1. if a b lss x (echo a b小于x)
复制代码

作者: lixiaodaoaaa    时间: 2008-10-17 04:22     标题: 特别感谢pusofalse 的教程

〓〓〓〓 〓〓〓〓 〓〓〓〓 〓〓〓〓 〓〓〓〓 〓〓〓〓 〓〓〓〓 〓〓〓〓 〓〓〓
                                                    自己再分析下

在学习这篇文章的时候特别感谢pusofalse的指点

我把pusofalse的某些辅导我的东西帖出来,一起看下

  1. @echo off
  2. color b0
  3. title set 比较大小练习
  4. @mode  con cols=30 lines=15
  5. set a= 150
  6. set b= 80
  7. if not a  lss b    echo a 他吗的造反了,竟然大于b了,哈哈
  8. echo.&echo.
  9. echo.&echo.
  10. pause
复制代码
我运行了,竟然出错了,明明是 a >b 的,现在怎么出错了呢?

怪了。经过pusofalse的指点

理由是这样的....
───────────────────────────────────────

这句 if not a lss b  echo a 他吗的造反了,竟然大于b了,哈哈

系统识别为 a 和b为常量,而并非变量,所以他判断的是常量的大小

系统规定  a<A<b<B<c<C<d<D<e.......<z<Z 这是字母从小到大的顺序

所以 以上代码并不显示

必须改成
  1. @echo off
  2. color b0
  3. title set 比较大小练习
  4. @mode  con cols=30 lines=15
  5. set a= 150
  6. set b= 80
  7. if not %a%  lss %b%    echo a 他吗的造反了,竟然大于b了,哈哈
  8. echo.&echo.
  9. echo.&echo.
  10. pause
复制代码
这样系统才认识a是变量 ,是set设定的值 150,仅仅 a ,就是一个常量。

%a% 就可以识别变量,那%a% 与%%a 又有什么区别呢

于是乎,我又去问pusofalse了,呵呵

他说。。%%a 是for 命令的变量,在for命令里会被识别

%a% 是set命令的变量,在set命令里会被识别为变量。
  1. for %%a in (1 2 3) do echo %%a
  2. pause
复制代码
而不是下面的代码,下面的代码运行就出现错误。呵呵
。。
  1. @echo off
  2. for %a% in (1 2 3) do echo %a%
  3. pause
复制代码
其他 pusofalse 还说 for 命令中的 大小写是区分的,

是不一样的。例如 %%A 与%%a 是不一样的

下面的代码就出错。
  1. @echo off
  2. for %%A in (1 2 3) do echo %%a
  3. pause
复制代码
而在set 中并不区分 大小写。


═╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬
特别感谢pusofalse的解答。我把他说的都写上来了,以前学习批处理,见for  if  set

就跑。说自己不搞这些,太难,看来,我必须搞了,搞了一年多,这命令不懂,很难

杀进 批处理的大门!

═╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬══╬╬


[ 本帖最后由 lixiaodaoaaa 于 2008-10-17 05:07 编辑 ]
作者: Batcher    时间: 2008-10-17 10:03

建议在【example6】中增加一条:如何判断指定的文件a.txt是否存在(要求能够排除同名文件夹的干扰)
作者: andy七少    时间: 2011-10-17 10:48

好教程,很容易理解~~
作者: wangx    时间: 2013-9-17 15:42

总结的很好啊,谢谢分享,每天都进步一点。




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2