[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]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

评分人数

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

绕晕        底层!!和%%的区别。。。。   我的理解是!!作解析比%%更晚,所以在if执行期间取得相应的变量名。而%%在执行批处理之前,先进行了%%的预处理(变量替换)。

TOP

讨论的很细致啊。

TOP

感谢版主授教,学了不少!

TOP

晕了,搞错了!
两次运行结果不一样!
是我这边出问题了!
麻烦随风版主了!
总结了下:
都是坏习惯惹的祸!
第一次测试时无意之中在=号后加了个空格
以为没赋值给变量!


再次感谢随风版主,今后一定改掉所有坏习惯!不能偷懒少了引号!

[ 本帖最后由 zjw767676 于 2009-4-8 00:24 编辑 ]
有一种爱叫放弃

TOP

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

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

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

TOP

  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set "ab cd="
  4. ::未赋值
  5. set "var= "
  6. if defined ab!var!cd (echo ab cd 被定义了) else echo ab cd 没有被定义
  7. pause
复制代码
显示没有定义
下面的代码无论是否赋值给ab cd都显示被定义了
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. set "ab cd="
  4. set "var=ab cd"
  5. if defined !var! (echo ab cd 被定义了) else echo ab cd 没有被定义
  6. pause
复制代码
不知随风版主理解我的意思了吗?

[ 本帖最后由 zjw767676 于 2009-4-8 00:12 编辑 ]
有一种爱叫放弃

TOP

回复 11楼 的帖子

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

TOP

我的意思是这样不能判断变量ab cd是否为空!
引号已加,感谢指正!!!!
有一种爱叫放弃

TOP

回复 9楼 的帖子

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

TOP

请随风版主测试以下代码
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. set "ab cd= "
  4. set "var=ab cd"
  5. if defined !var! (echo ab cd 被定义了) else echo ab cd 没有被定义
  6. pause
复制代码
个人认为这里判断的是变量var而不是ab cd

[ 本帖最后由 zjw767676 于 2009-4-7 23:39 编辑 ]
有一种爱叫放弃

TOP

万恶的空格,做wxcute 版主的中级练习题时花了1个多小时调试,最后发现多了个空格,哎

TOP

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

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

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

TOP

回复 4楼 的帖子

感谢版主的热心,3楼并非问题,只是建议^_^
bjsh 兄的帖子我很早前也看过,还有你们在verybat讨论预处理等相关内容的帖子我也看过,写的都挺好。这里只是建议楼主在我们bathome也做一下深入的讲解,呵呵。
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

呵呵,随风兄的研究果真不一般啊
我遇到这样的问题,一般都是避过(为什么不弄一个没有空格的变量名呢?),惭愧,惭愧!

TOP

返回列表