![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-06 03:02 |
共 48,039 主题排行 / 350,124 发帖 / 今日 2 篇 / 48,251 会员排行 |
| DOS批处理 & 脚本技术(批处理室) » [原创]变量延迟详解(新手推荐) |
| 可打印版本 25,470 / 111 |
| 第1楼 nforce1 | 发表于 2007-03-09 08:52 |
| 初级用户 发帖 16 积分 128 | |
|
[原创]变量延迟详解(新手推荐) 因工作关系一直没有太多时间泡在论坛上,每次上本论坛都很匆忙,注册几个月以来第一次发贴(因为本人太菜,不敢发帖),真有点不好意思!希望大家多多支持! 本帖只“照顾”新手,老鸟略过,哈! 以下是偶根据论坛内的帖子得出的结论,如有错漏敬请指正! 首先要特别感谢willsort老大写的这帖子,偶是从中得到启发的! http://www.cn-dos.net/forum/viewthread.php?tid=20733 下面在讨论过程中,偶会插入一些“废话”,如果你不喜欢看我写的“废话”,可以跳过。它与本文讨论的中心完全无关!不过偶还是建议大家看看,哈! 这段可跳过: 同学们上课啦,第一天来这里任教,必须先做个自我介绍。偶叫金城武,啊啊~~~~~~不,不是,一时口快说错了, 偶姓贾,不好意思!由于近日忙于研究“鬼武者”,所以忘了自己的姓氏!什么,说我现在才玩鬼武者,哎!没办法啊,偶穷啊,口袋里总是掏不起这几块钱买啊。“几块钱?”众人议论纷纷。什么,又说我买盗版,啊~~啊~~~这~~这不在本文的讨论范围啊~~~~~说完台下众人举起砖头……^_^ 这是正文不可跳过: willsort老大上面的帖子,对于新手来说比较难理解。不过没关系,我们先分析一个例子,同样是引用willsort老大的。本例启用了变量延迟,是个正确的例子! 例1: 将上面代码保存为.bat双击执行后会显示“Will Sort”字符串,下面将讲解每个语句的意思: 1.@echo off & setlocal EnableDelayedExpansion 关闭命令回显,并启用变量延迟 2.for /f "tokens=* delims=" %%i in ("Hello world.") do ( for命令及其参数的使用,请大家在论坛里搜索相关字眼。限于篇幅问题,这里不作讨论。如果此时你不明白它的意思,那么你就当它的作用是把字符串“Hello world.”赋值给%%i好了,当然这只是权宜之计,以后一定要学习for的使用! 3.set n=%%i 把%%i的值(即Hello world.)赋予给变量n,这个大家都知道吧 4.set n=!n:ld.=t! 这里要讲讲set替换字符的功能了。这个语句的意思是,先获取变量n的值(此时n的值是“Hello world.”),然后将字符“t”替换字符“ld.”,然后再将替换后的结果再次赋值给变量n(此时n的值变为“Hello wort”)。至于set替换字符的编写格式,大家可以在CMD键入“set/?”找到“%PATH:str1=str2%”这段有说明 5.set n=!n:o w= S! 意思和上句一样,只是替换和被替换的内容不同。它是将“ S”替换“o w”(注意S前面和w前面都有个空格),其实willsort老大是想证明set替换字符是支持句点和空格的(第4句“ld”后面有个.)。此时n的值为“Hell Sort” 6.set n=!n:He=Wi! 这句不用说了吧,执行完这句后n的值为“Will Sort” 7.echo !n! 显示变量n的值 需要注意的是,一旦启用了变量延迟,就要用!号把变量括起来,而不能用%号。 好了,每句的意思已经说完了,下面要讲本帖真正要讨论的变量延迟的问题。 这里又要引用Will Sort老大的说明:当CMD读取for语句时,其后用一对圆括号闭合的所有语句将一同读取,并完成必要的预处理工作,这其中就包括环境变量的扩展,所以在for中的所有语句执行之前,所有的环境变量都已经被替换为for之前所设定的值,从而成为一个字符串常量,而不再是变量。 而为了能够在for语句内部感知环境变量的动态变化,CMD设计了延迟的环境变量扩展特性,也就是说,当CMD读取了一条完整的语句之后,它不会立即执行变量的扩展行为,而会在某个单条语句执行之前再进行扩展,也就是说,这个扩展行为被“延迟”了。 总的来说是,在没有启用变量延迟的情况下,凡是在括号内(即do里面)的变量,在执行for语句之前,就已经被替换成for语句之前其它命令对该变量所赋予的值。这句话不懂没关系,下面再看一个例子,看完你就会明白。 例2: 这和前面的例子差不多,只是所有!号都换成%号,这是个错误的例子。因为它没有启用变量延迟,也没有使用!号把变量括起来。我们看到它的执行结果是显示“ECHO 处于关闭状态”。 为什么会这样呢?原因是,在没有启用变量延迟的情况下,凡是在括号内(即do里面)的变量,在执行for语句之前,就已经被替换成for语句之前其它命令对该变量所赋予的值。 则是说在本例中的以下几句 set n=%%i set n=%n:ld.=t% set n=%n:o w= S% set n=%n:He=Wi% echo %n% 第一句能正常执行并达到它的目的,因为它只是单纯地将%%i的值赋予给变量n,所以没有任何问题。其它几句属这样情况:早在for语句执行前,CMD就急不切待地将这几句里面的所有变量n一同执行替换行为,替换为for之前,其它命令对n所设置的值,从而使n变成一个常量。但在本例中,for语句之前只有@echo off这句,并没有其它命令对n作过任何赋值行为,所以在for之前,变量n的值为空值。即是说,set n=%n:ld.=t% 这句里面的变量n,在CMD读取(注意是读取不是执行)完整个for语句后(这时还未轮到set执行自己的任务),就立刻被替换为一个空值,一个空值里面没有任何东西,所以就不存在一字符替换另一字符这种说法(没有东西怎么替换?)。最终到执行set n=%n:ld.=t%语句时,它只是获取一个空值,再给变量n赋予空值而已。其它几句也是一样原理。 所以,最后echo %n%的时候变量n还是个空值,而echo命令没有东西可以显示,就只有显示“ECHO 处于关闭状态”这句来说明自己的状态 通过这个例子的说明,相信大家已经知道变量延迟的作用吧!我们再回头来看看例1。 启用变量延迟后,在执行 set n=!n:ld.=t! set n=!n:o w= S! set n=!n:He=Wi! echo !n! 这些语句前,它们里面的变量n不会马上被CMD替换(启用延迟后,CMD变得有耐性啦^_^),而未被替换的话,那么n就还是变量,而不是常量。等到执行set n=!n:ld.=t!等这几句时,变量n才被替换。这样每个set命令都能感知变量n的任何变化,从而作出正确的替换行为。这就是变量延迟啦! 可跳过: 什么,说我讲得不好?没办法啊,因为偶太菜啊,只知道这些。偶只是淘两顿饭吃而已,望大家谅解啊,不要再拿砖头砸偶。。。不然偶就~~~~~~~~~~叫救命!^_^ 这是正文不可跳过: 不要以为只有for才要用变量延迟,下面这个例子同样需要 例3:这是个错误的例子 执行后依然显示“ECHO 处于关闭状态”。 原因是没有启用延迟,而且在set mm=girl&echo %mm%语句前没有其它命令对mm进行赋值。这时当CMD执行set mm=girl&echo %mm%语句前,就已经急不切待地把变量mm的值替换了,而又因为前面没给mm赋值,所以mm被替换为空值,变成常量。等到echo命令执行时,它其实是echo一个不会变化的常量,本例中即是空值。 有人会问,echo前面不是给mm赋值了吗? 这个就要关系到CMD解释命令的步骤,大家可以参详本帖开头willsort的帖子。 总的来说是,如果不启用变量延迟,在本例中,echo是不会理会也不会知道,它前面(指同一行语句)是否有其它命令给mm赋值。它只会从set mm=girl&echo %mm%这句以上的语句中获取它所要显示的变量的内容,也就是说,上一行或上几行的命令将mm设置成什么值,echo命令就显示什么值。 大家这样做就明白了: 看看显示什么结果就知道了! 这样编写例3才正确: 开启了变量延迟,变量扩展(替换)的行为就推迟到echo命令执行时,这时echo能感知它前面的命令(本例的set)对变量mm做了什么“坏事”,从而作出正确的判断并执行 好了全篇完了,下课! 突然,门外传来几只“恐龙”的嚎叫声:把那小子抓回去,胆敢趁着节日咱们游山玩水的时候偷走!! 2分钟后,“恐龙战队”押着这小子来到一个美丽壮观的“城堡”面前,正门上方写着“XX疯人院”,哈哈! 愿天下美女妇女节快乐,一天比一天美(包括在浏览本贴的你)!!---汗,这里有女同胞吗??有的请举手!呵呵!39们也一起感受节日的气氛吧! 这帖本来是想上午发的,但因工作关系,到现在才有空,无奈啊! 以上这些“废话”只是想令大家阅读这贴时能增添几分气氛,增加大家的阅读兴趣,令大家在学习过程中轻松轻松而已。如有得罪,敬请批评指正! [ Last edited by nforce1 on 2007-4-2 at 09:26 AM ] |
|
| 第2楼 electronixtar | 发表于 2007-03-09 09:47 |
| 铂金会员 发帖 2,672 积分 7,493 | |
|
顶,沙发
|
|
| 第3楼 oilio | 发表于 2007-03-09 09:52 |
| 高级用户 发帖 303 积分 641 | |
|
呵呵,是写给新手看的,支持你一下。写这么多也不容易。
|
|
| 第4楼 nforce1 | 发表于 2007-03-09 09:58 |
| 初级用户 发帖 16 积分 128 | |
|
好不容易发帖,忘了自己顶一个~~!哈
谢谢electronixtar与 oilio两位前辈的支持!! |
|
| 第5楼 ieutk | 发表于 2007-03-09 11:44 |
| 初级用户 发帖 48 积分 107 | |
|
谢谢楼主,这样的贴子对新手最好了,新手有福啦!
|
|
| 第6楼 namejm | 发表于 2007-03-09 11:57 |
| 荣誉版主 发帖 1,737 积分 5,226 来自 成都 | |
|
写得不错,对新手会很有帮助,收入经典帖子索引。
|
|
| 第7楼 bbq123bbq | 发表于 2007-03-09 16:58 |
| 初级用户 发帖 77 积分 197 | |
|
收藏拉
|
|
| 第8楼 liujunhjl | 发表于 2007-03-09 18:39 |
| 新手上路 发帖 1 积分 2 来自 邢台 | |
|
写的真不错,就是太长了,就怕看不懂,不过还是不错的,顶!!!!!
|
|
| 第9楼 xycoordinate | 发表于 2007-03-09 23:01 |
| 中级用户 发帖 228 积分 493 来自 安徽 | |
21世纪最缺什么? 。。。。。。 道理很多人都知道,但是能够说明白,让更多的人知道, 一个字:难! |
|
| 第10楼 nzisisco | 发表于 2007-03-09 23:49 |
| 初级用户 发帖 47 积分 107 | |
|
好耶````适合我这种新手看
|
|
| 第11楼 sbyguli | 发表于 2007-03-10 10:44 |
| 新手上路 发帖 10 积分 18 | |
|
好帖子啊~谢谢楼主的分析!
|
|
| 第12楼 shuaigeya | 发表于 2007-03-10 21:04 |
| 初级用户 发帖 19 积分 42 | |
|
精彩 学习了
|
|
| 第13楼 htysm | 发表于 2007-03-12 22:40 |
| 高级用户 发帖 415 积分 866 | |
|
偶喜欢楼主.强.DOS联盟有福了.
|
|
| 第14楼 willsion | 发表于 2007-03-13 01:41 |
| 高级用户 发帖 312 积分 793 | |
|
帖子不错,学习了。
|
|
| 第15楼 willsion | 发表于 2007-03-13 01:44 |
| 高级用户 发帖 312 积分 793 | |
|
另外,有个疑问,不知道变量延迟是否有副作用,如果没有副作用的话
,那每个程序头干脆插上setlocal EnableDelayedExpansion语句了。就象 @echo off一样。 |
|
| 1 2 3 4 … 8 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |