标题: 批处理中的if defined 需知 2009-5-10 更新 [打印本页]
作者: 随风 时间: 2008-10-3 10:41 标题: 批处理中的if defined 需知 2009-5-10 更新
if defined 需知
:: code 随风 @bbs.bathome.net 2008-10-01
if defined 命令 使用需注意的地方。
我们经常使用 if defined 命令来判断某个变量是否被定义过。这个命令非常有用,使用频率也颇高。
但是 if defined 确有些错误的用法容易被忽略,个人曾吃过亏,费了九牛二虎之力才找到出错原因。
也许各路高人早以心知肚明,但网上却好像很少有人讨论。(也许是我孤陋寡闻了,呵呵)
现就个人经验作个总结,知道的一笑而过,不知道的可以少走些弯路。
错误的欢迎指出。。。
问题一: 空格问题。
测试 代码 1-1- ::代码 1-1
- @echo off
- set ab cd=fff
- if defined ab cd (echo ab cd 被定义了) else echo ab cd 没有被定义
- pause
复制代码
什么都没显示,直接执行后面的 pause 命令了,按说应该显示 “ab cd 被定义了”才对呀。
问题出在空格上
总结: if defined 这里不能有空格。
再测试 代码 1-2- ::代码 1-2
- @echo off
- set ab cd=fff
- set "var= "
- if defined ab%var%cd (echo ab cd 被定义了) else echo ab cd 没有被定义
- pause
- [code]
- 我们把空格用变量来代替,结果还是一样,郁闷!难道就不能检测含空格的变量名是否被定义过吗?
- 不信邪,继续。。。
- 测试 代码 1-3
- [code]
- ::代码 1-3
- @echo off
- setlocal enabledelayedexpansion
- set ab cd=fff
- set "var= "
- if defined ab!var!cd (echo ab cd 被定义了) else echo ab cd 没有被定义
- pause
复制代码
乖乖,你终于出来了。。。!
再试试多个空格时如何?测试代码 1-4- ::代码 1-4
- @echo off
- setlocal enabledelayedexpansion
- set a b c d e=fff
- set "var= "
- if defined a!var!b!var!c!var!d!var!e (
- echo a b c d e 被定义了
- ) else echo a b c d e 没有被定义
- pause
复制代码
哈哈,真的可以。。。
但是这样似乎也太麻烦了点。!!若是含多个空格,岂不是要写上一大堆的变量??
试试将变量名赋值给别的变量试试。。
看 代码 1-5- ::代码 1-5
- @echo off
- setlocal EnableDelayedExpansion
- set ab cd=fff
- set "var=ab cd"
- if defined !var! (echo ab cd 被定义了) else echo ab cd 没有被定义
- pause
复制代码
嗯,果然可以。。这下简单多了。。。
但是需注意的是仍然得用!!来引用变量。
总结:
检测含空格的变量名是否被定义过,需开启延迟变量,
并把 if defined 这里的所有空格都用变量来代替
或是将变量名赋值给别的变量,再用!!来引用这个新的变量。
再试试 代码 1-6
看看在 for 中是否能行?感觉应该是可以的,因为for的 %%i 也是变量啊。
试试再说。。- ::代码 1-6
- @echo off
- set a b c d=fff
- for /f "delims=" %%i in ("a b c d") do (
- if defined %%i (echo %%i 被定义了) else echo %%i 没有被定义
- )
- pause
复制代码
果然可以,而且可以不用开启变量延迟。
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
问题二: 变量的截取。
先看一段代码- ::代码 2-1
- @echo off
- setlocal EnableDelayedExpansion
- set a=fff
- set var=abc
- if defined !var:~0,1! (echo a 被定义了) else echo a 没有被定义
- pause
复制代码
居然又是老问题 ???!!!
明明开启了延迟变量啊。。!
试试不用变量的延迟扩展看看- ::代码 2-2
- @echo off
- setlocal EnableDelayedExpansion
- set a=fff
- set var=abc
- if defined %var:~0,1% (echo a 被定义了) else echo a 没有被定义
- pause
复制代码
可以了,还真是麻烦,忽左忽右、忽上忽下的,头的晕了。。。
那么在 for 中呢?
代码 2-3- ::代码 2-3
- @echo off
- setlocal EnableDelayedExpansion
- set "a=fff"
- set "b=fff"
- set "c=fff"
- set "var=abc"
- for /l %%i in (0 1 2) do (
- if defined !var:~%%i,1! (echo a 被定义了) else echo a 没有被定义
- )
- pause
复制代码
竟然一闪而过,语法错误了。。汗。。!
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
最后总结:
用 if defined 判断某个变量是否被定义过时需注意以下2点:
1、不能直接输入空格,有空格时需用变量来代替,且必须是用双!!来引用这个值含空格的变量
也就是必须开启延迟变量,或者将需判断的变量名赋值给 for 的 %%i 变量。
2、若判断的变量名需要使用变量的字符截取功能时,则与上面的正好相反。
即:不能使用!!来引用变量,即使是在for中也是一样。
更新:但可以 if defined !num:~1! 或 if defined !num:~-1!
不能同时指定两个数字,或者说不能出现逗号。
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
[ 本帖最后由 随风 于 2009-5-10 12:44 编辑 ]
作者: yslyxqysl 时间: 2008-10-3 14:58
哈哈,我从来都是用if not "%var%"==""
作者: Batcher 时间: 2008-10-3 21:16
授人以鱼,不如授人以渔。
随风 兄何不从批处理的执行机制等方面入手,讲解一下为什么会出现这些问题?
作者: zqz0012005 时间: 2008-10-3 21:33
与变量含空格类似,还有变量值含引号的问题- @echo off
- >a.txt echo "
- set var="
- setlocal EnableDelayedExpansion
- for /f %%a in (a.txt) do (
- if %var:"=quote%==quote echo equal
- if "%var:"=quote%"=="quote" echo equal
- rem if !var:"=quote!==quote echo equal
- rem if "!var:"=quote!"=="quote" echo equal
- if "%%a"=="!var!" echo equal
- rem if "%%a"=="%var%" echo equal
- rem 注释掉的语句会出错
- )
- pause
复制代码
3楼提出的问题可以参考此贴:
简析环境变量和变量延迟特殊字符以及中介法的微妙关系
http://www.cn-dos.net/forum/viewthread.php?tid=30884
作者: youxi01 时间: 2008-10-3 23:13
呵呵,随风兄的研究果真不一般啊
我遇到这样的问题,一般都是避过(为什么不弄一个没有空格的变量名呢?),惭愧,惭愧!
作者: Batcher 时间: 2008-10-3 23:24 标题: 回复 4楼 的帖子
感谢版主的热心,3楼并非问题,只是建议^_^
bjsh 兄的帖子我很早前也看过,还有你们在verybat讨论预处理等相关内容的帖子我也看过,写的都挺好。这里只是建议楼主在我们bathome也做一下深入的讲解,呵呵。
作者: 随风 时间: 2008-10-7 01:45
原帖由 Batcher 于 2008-10-3 21:16 发表
授人以鱼,不如授人以渔。
随风 兄何不从批处理的执行机制等方面入手,讲解一下为什么会出现这些问题?
非常遗憾,对命令机制的问题,我也是知其然,不知其所以然。。。
[ 本帖最后由 随风 于 2010-9-2 11:06 编辑 ]
作者: firewolf85 时间: 2008-12-10 19:54
万恶的空格,做wxcute 版主的中级练习题时花了1个多小时调试,最后发现多了个空格,哎
作者: zjw767676 时间: 2009-4-7 23:16
请随风版主测试以下代码- @echo off
- setlocal EnableDelayedExpansion
- set "ab cd= "
- set "var=ab cd"
- if defined !var! (echo ab cd 被定义了) else echo ab cd 没有被定义
- pause
复制代码
个人认为这里判断的是变量var而不是ab cd
[ 本帖最后由 zjw767676 于 2009-4-7 23:39 编辑 ]
作者: 随风 时间: 2009-4-7 23:23 标题: 回复 9楼 的帖子
不知道你想说明什么?
我运行你的代码显示 ab cd 被定义了
这和我顶楼说的不相违背啊?你的代码把 ab cd 定义了一个空格,不知道你是故意的还是无意的。若是有意的应加上引号,否则很容易让人误解。
作者: zjw767676 时间: 2009-4-7 23:43
我的意思是这样不能判断变量ab cd是否为空!
引号已加,感谢指正!!!!
作者: 随风 时间: 2009-4-7 23:47 标题: 回复 11楼 的帖子
凭什么说你的代码不能判断变量ab cd是否为空
代码中 ab cd 本来就不是空,当然会显示 ab cd 被定义了,有什么错?
作者: zjw767676 时间: 2009-4-8 00:03
- @echo off
- setlocal enabledelayedexpansion
- set "ab cd="
- ::未赋值
- set "var= "
- if defined ab!var!cd (echo ab cd 被定义了) else echo ab cd 没有被定义
- pause
复制代码
显示没有定义
下面的代码无论是否赋值给ab cd都显示被定义了- @echo off
- setlocal EnableDelayedExpansion
- set "ab cd="
- set "var=ab cd"
- if defined !var! (echo ab cd 被定义了) else echo ab cd 没有被定义
- pause
复制代码
不知随风版主理解我的意思了吗?
[ 本帖最后由 zjw767676 于 2009-4-8 00:12 编辑 ]
作者: 随风 时间: 2009-4-8 00:09
原帖由 zjw767676 于 2009-4-8 00:03 发表
下面的代码无论是否赋值给ab cd都显示被定义了
1、你确定你的第二个代码无论是否赋值给ab cd都显示被定义了吗?
2、加对引号就这么难吗?
作者: zjw767676 时间: 2009-4-8 00:09
晕了,搞错了!
两次运行结果不一样!
是我这边出问题了!
麻烦随风版主了!
总结了下:
都是坏习惯惹的祸!
第一次测试时无意之中在=号后加了个空格
以为没赋值给变量!
再次感谢随风版主,今后一定改掉所有坏习惯!不能偷懒少了引号!
[ 本帖最后由 zjw767676 于 2009-4-8 00:24 编辑 ]
作者: yadngah1984 时间: 2010-9-20 14:30
感谢版主授教,学了不少!
作者: wangx 时间: 2013-9-16 16:28
讨论的很细致啊。
作者: ai20110304 时间: 2018-8-28 17:01
绕晕 底层!!和%%的区别。。。。 我的理解是!!作解析比%%更晚,所以在if执行期间取得相应的变量名。而%%在执行批处理之前,先进行了%%的预处理(变量替换)。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |