[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

批处理中的if defined 需知 2009-5-10 更新

if defined 需知
:: code 随风 @bbs.bathome.net 2008-10-01
if defined 命令 使用需注意的地方。
我们经常使用 if defined 命令来判断某个变量是否被定义过。这个命令非常有用,使用频率也颇高。
但是 if defined 确有些错误的用法容易被忽略,个人曾吃过亏,费了九牛二虎之力才找到出错原因。
也许各路高人早以心知肚明,但网上却好像很少有人讨论。(也许是我孤陋寡闻了,呵呵)
现就个人经验作个总结,知道的一笑而过,不知道的可以少走些弯路。
错误的欢迎指出。。。
问题一: 空格问题。
测试  代码 1-1
  1. ::代码 1-1
  2. @echo off
  3. set ab cd=fff
  4. if defined ab cd (echo ab cd 被定义了) else echo ab cd 没有被定义
  5. pause
复制代码
什么都没显示,直接执行后面的 pause 命令了,按说应该显示 “ab cd 被定义了”才对呀。
问题出在空格上
总结: if defined 这里不能有空格。
再测试  代码 1-2
  1. ::代码 1-2
  2. @echo off
  3. set ab cd=fff
  4. set "var= "
  5. if defined ab%var%cd (echo ab cd 被定义了) else echo ab cd 没有被定义
  6. pause
  7. [code]
  8. 我们把空格用变量来代替,结果还是一样,郁闷!难道就不能检测含空格的变量名是否被定义过吗?
  9. 不信邪,继续。。。
  10. 测试 代码 1-3
  11. [code]
  12. ::代码 1-3
  13. @echo off
  14. setlocal enabledelayedexpansion
  15. set ab cd=fff
  16. set "var= "
  17. if defined ab!var!cd (echo ab cd 被定义了) else echo ab cd 没有被定义
  18. pause
复制代码
乖乖,你终于出来了。。。!
再试试多个空格时如何?测试代码 1-4
  1. ::代码 1-4
  2. @echo off
  3. setlocal enabledelayedexpansion
  4. set a b c d e=fff
  5. set "var= "
  6. if defined a!var!b!var!c!var!d!var!e (
  7.   echo a b c d e 被定义了
  8. ) else echo a b c d e 没有被定义
  9. pause
复制代码
哈哈,真的可以。。。
但是这样似乎也太麻烦了点。!!若是含多个空格,岂不是要写上一大堆的变量??
试试将变量名赋值给别的变量试试。。
看 代码 1-5
  1. ::代码 1-5
  2. @echo off
  3. setlocal EnableDelayedExpansion
  4. set ab cd=fff
  5. set "var=ab cd"
  6. if defined !var! (echo ab cd 被定义了) else echo ab cd 没有被定义
  7. pause
复制代码
嗯,果然可以。。这下简单多了。。。
但是需注意的是仍然得用!!来引用变量。
总结:
   检测含空格的变量名是否被定义过,需开启延迟变量,
   并把 if defined 这里的所有空格都用变量来代替
   或是将变量名赋值给别的变量,再用!!来引用这个新的变量。
再试试  代码 1-6
看看在 for 中是否能行?感觉应该是可以的,因为for的 %%i 也是变量啊。
试试再说。。
  1. ::代码 1-6
  2. @echo off
  3. set a b c d=fff
  4. for /f "delims=" %%i in ("a b c d") do (
  5.    if defined %%i (echo %%i 被定义了) else echo %%i 没有被定义
  6. )
  7. pause
复制代码
果然可以,而且可以不用开启变量延迟。
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
问题二: 变量的截取。
先看一段代码
  1. ::代码 2-1
  2. @echo off
  3. setlocal EnableDelayedExpansion
  4. set a=fff
  5. set var=abc
  6. if defined !var:~0,1! (echo a 被定义了) else echo a 没有被定义
  7. pause
复制代码
居然又是老问题 ???!!!
明明开启了延迟变量啊。。!
试试不用变量的延迟扩展看看
  1. ::代码 2-2
  2. @echo off
  3. setlocal EnableDelayedExpansion
  4. set a=fff
  5. set var=abc
  6. if defined %var:~0,1% (echo a 被定义了) else echo a 没有被定义
  7. pause
复制代码
可以了,还真是麻烦,忽左忽右、忽上忽下的,头的晕了。。。
那么在 for 中呢?
代码 2-3
  1. ::代码 2-3
  2. @echo off
  3. setlocal EnableDelayedExpansion
  4. set "a=fff"
  5. set "b=fff"
  6. set "c=fff"
  7. set "var=abc"
  8. for /l %%i in (0 1 2) do (
  9.   if defined !var:~%%i,1! (echo a 被定义了) else echo a 没有被定义
  10. )
  11. pause
复制代码
竟然一闪而过,语法错误了。。汗。。!
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
最后总结:
   用 if defined 判断某个变量是否被定义过时需注意以下2点:
   1、不能直接输入空格,有空格时需用变量来代替,且必须是用双!!来引用这个值含空格的变量
      也就是必须开启延迟变量,或者将需判断的变量名赋值给 for 的 %%i 变量。
   2、若判断的变量名需要使用变量的字符截取功能时,则与上面的正好相反。
      即:不能使用!!来引用变量,即使是在for中也是一样。

更新:但可以 if defined !num:~1! 或 if defined !num:~-1!
         不能同时指定两个数字,或者说不能出现逗号。

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

[ 本帖最后由 随风 于 2009-5-10 12:44 编辑 ]
5

评分人数

技术问题请到论坛发帖求助!

原帖由 Batcher 于 2008-10-3 21:16 发表
授人以鱼,不如授人以渔。
随风 兄何不从批处理的执行机制等方面入手,讲解一下为什么会出现这些问题?

非常遗憾,对命令机制的问题,我也是知其然,不知其所以然。。。

[ 本帖最后由 随风 于 2010-9-2 11:06 编辑 ]
技术问题请到论坛发帖求助!

TOP

回复 9楼 的帖子

不知道你想说明什么?
我运行你的代码显示 ab cd 被定义了
这和我顶楼说的不相违背啊?你的代码把 ab cd 定义了一个空格,不知道你是故意的还是无意的。若是有意的应加上引号,否则很容易让人误解。
技术问题请到论坛发帖求助!

TOP

回复 11楼 的帖子

凭什么说你的代码不能判断变量ab cd是否为空
代码中 ab cd 本来就不是空,当然会显示 ab cd 被定义了,有什么错?
技术问题请到论坛发帖求助!

TOP

原帖由 zjw767676 于 2009-4-8 00:03 发表

下面的代码无论是否赋值给ab cd都显示被定义了

1、你确定你的第二个代码无论是否赋值给ab cd都显示被定义了吗?
2、加对引号就这么难吗?
技术问题请到论坛发帖求助!

TOP

返回列表