![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-04 21:52 |
共 48,038 主题排行 / 350,123 发帖 / 今日 0 篇 / 48,251 会员排行 |
| DOS批处理 & 脚本技术(批处理室) » 简析环境变量和变量延迟特殊字符以及中介法的微妙关系 |
| 可打印版本 8,829 / 29 |
| 第1楼 bjsh | 发表于 2007-05-23 15:52 |
| 银牌会员 发帖 621 积分 2,000 | |
|
简析环境变量和变量延迟特殊字符以及中介法的微妙关系 已作修改
本文主要以例子展开了讨论: 对每个例子的结果进行分析;并揭示其中的一些现象; 例一: 结果为
(注意到 此时setlocal默认为disabledelayedexpansion !!不被识别) 因此把%mk%看做环境变量被替换掉;而mk没有被定义因此%mk%被替换为空 再来看加了setlocal enabledelayedexpansion后会是怎样; 例二: 结果为
注意到 此时setlocal声明为enabledelayedexpansion 因此把!tsd!和%mk%均被看做环境变量而被替换掉;而tsd和mk没有被定义因此均被替换为空 (由于优先级的不同;%mk%将在预处理被先被替换,然后!tsd!被替换;原因后面有讲到) 如果把kljlk!tsd!21%mk%gd放到t.txt然后 再通过%%a做为中介进行传递后会有什么现象呢 例三: 结果为:
如果按照上面所说的此时%mk%应该被替换为空; 但是这里经过一个%%a的中介;此时的结果不会把%mk%替换;即使mk环境变量有定义也不会替换掉;而是按字面输出; 实际上这跟cmd的预处理机制有关; 当CMD读取for语句时,他的所有语句将一同被读取,并完成预处理工作,这其中就包括环境变量%%的扩展; 因为字符串在文本中 并没有以字符串的形式出现在 for语句中;因此其中的%%躲过了预处理机制; 但是当启用延迟环境变量后 例如: 例四 结果为:
首先他会和上面一样对for所有语句一起读取;完成对%%的扩展;(%%的优先级高) 然后当CMD读取了一条完整的语句之后, 它不会立即执行变量的扩展行为,而会在某个单条语句执行之前再进行扩展,也就是说,这个扩展行为被“延迟”了 例如在set "var=%%a"时 只有执行到这条命令前才会对这条命令进行扩展; 而此时%%a已经被kljlk!tsd!21%mk%gd所代替;因此将会对其中的!!进行扩展. 他会识别其中是否存在!;此时的扩展只处理!!而不处理%%(因为对%%的处理过程在先前已经进行完;而那时因为字符串在文本中 并没有以字符串的形式出现在 for语句中;因此其中的%%躲过了预处理机制;); 然而只有当该字符串中含有!时, cmd才会对该字符串进行再次处理; 举例: 例五: t.txt的内容
结果为:
注意到 第一行的 ^ 已经不存在了;(所在行包含!!) 而第三行的^没有被处理;(所在行不包含!!) (包含一个!也会对^进行处理;) 由此可见 启用延迟环境变量后 ; 在每次执行语句前; cmd会检查是否含有!; 如果存在就对其进行必要的预处理后再执行. 注:此时setlocal默认为disabledelayedexpansion因此!tsd!是因为不给识别而不被替换和%mk%不被替换的原因不同. 如果想强迫进行二次转变(即把%mk%的值按其环境变量值警醒替换)再赋值给var可以使用 call set "var=%%a" 也就是说: 例六: 的结果则为:
call set "var=%%a" 实际上是让命令解释器再来一次预处理来达到目的的 再来看%%a另一个例子 例七: 结果为:
大家都知道这是因为里面有特殊字符; 但是看下面的例子;把^&*&^^&%$%^%$#$1213<>:Lksgsd放到t.txt中;用%%a做为中介后: 例七: 结果则为:
所有的都是原样输出;丝毫没有因为特殊字符而受影响;(原因上面已讲到) 注:如果t.txt中有直接回车的空行则会跳过;原因在for本身而不是%%a; 再来个!var!的特殊例子 例八: 结果为:
结果出错 做如下的修改 例九: 结果为:
结果正确; 但是此种方法仍然受上面所述的原因影响; 比如如果var=后面的值含有!!和%%等则会发生替换;还有比如中间有:则会与set发生关系而导致结果不准确; 当然可以利用%%a中介可以避免 %% 被替换;但是!!却有上述原因没法逃过被替换; 最后给出个综合应用的例子: 对文件指定行进行输出;不论是否含有特殊字符: 这里就把整个文件输出;对指定行可以修改为 findstr /n .* test.txt^|findstr "^10:" 等; 短短的几行代码包含了很多技巧; 测试文本: test.txt
并没有经过大量的测试;诸位帮忙测试; [ Last edited by bjsh on 2007-5-27 at 12:03 PM ] |
|
| 第2楼 namejm | 发表于 2007-05-24 07:54 |
| 荣誉版主 发帖 1,737 积分 5,226 来自 成都 | |
|
测试了不少内容,并把这个过程转化为一篇长帖,佩服你的耐心。
我觉得,一切的一切,应该和CMD的预处理机制有关,可惜水平有限,难以做深入的分析——这个时候,习惯性地又想起了willsort,不知道何年何月才能又看到他那深入本质的分析。 |
|
| 第3楼 lxmxn | 发表于 2007-05-24 08:48 |
| 版主 发帖 4,938 积分 11,386 | |
|
bjsh 真是很有耐心,学习。
|
|
| 第4楼 guxingyibei | 发表于 2007-05-24 09:12 |
| 初级用户 发帖 32 积分 68 | |
|
服了! bjsh版主太厉害了! 我以前不太了解那个setlocal enabledelayedexpansion 到底有什么用,现在知道了不少了!而且最重要的是他们之间详细的关联,很受益!
我还从中学到了 echo 和 echo. 的区别,虽然不是很清楚! 还有那个findstr /n .* test.txt ,"."后面有*和没有*的区别, 非常感谢!! |
|
| 第5楼 mtiankong | 发表于 2007-05-25 14:27 |
| 初级用户 发帖 38 积分 70 | |
|
向楼主学习~~~
|
|
| 第6楼 Vampire | 发表于 2007-05-25 14:39 |
| 初级用户 发帖 78 积分 176 | |
|
喜欢看深入的分析。收藏。
|
|
| 第7楼 qzwqzw | 发表于 2007-05-27 00:52 |
| 银牌会员 发帖 636 积分 2,343 | |
Originally posted by bjsh at 2007-5-23 15:52: 请恕冒昧 我感觉这一句很有问题 for不会为特殊字符加转义符号 这样会额外增加它的预处理负担 对于例3的结果分析 应该是因为"kljlk!tsd!21%mk%gd"这个串没有被预处理 因为只有预处理过程才会处理这些特殊字符 也就是说 这个串因为藏在文件中 “躲过了”cmd的预处理机制审查 所以得以全身 至于例5的结果分析 那是因为对!!的分析和其它字符不属于同一阶段的预处理范畴 也就是说 对%"这些是初审 而对!则是复审 过的了初审的! 未必过的了复审 全看命令延迟扩展这根指针的指向呢 总的来说 因为cmd处理所有字符都是有先有后 所以必然会产生所谓优先级的问题 比如%的优先级会很高 因为它很早就被转义解释了 "和^都不会对它发生作用 |
|
| 第8楼 bjsh | 发表于 2007-05-27 10:22 |
| 银牌会员 发帖 621 积分 2,000 | |
|
是的;
确实是我理解有误; 已经修改 多谢qzwqzw兄的指点; 当CMD读取for语句时,他的所有语句将一同被读取,并完成预处理工作,这其中就包括环境变量%%的扩展; 因为字符串在文本中 并没有以字符串的形式出现在 for语句中;因此其中的%%躲过了预处理机制; 启用延迟环境变量后 首先他会和上面一样对for所有语句一起读取;完成对%%的扩展; 然后当CMD读取了一条完整的语句之后,他会识别其中是否存在!!;此时的扩展只识别!!而不识别%%; 只用当该字符串中含有!!, cmd才会对该字符串进行再次处理; 举例: t.txt的内容为
结果为:
注意到 第一行的 ^ 已经不存在了; 而第三行的^没有被处理; 由此可见 启用延迟环境变量后 ; 在每次执行语句前; cmd会检查是否含有!!; 如果存在就对其进行必要的预处理后再执行. [ Last edited by bjsh on 2007-5-27 at 10:58 AM ] |
|
| 第9楼 oilio | 发表于 2007-05-27 16:48 |
| 高级用户 发帖 303 积分 641 | |
|
佩服啊,我就没有这种耐心,有的时候测试最多只能做几分钟。
|
|
| 第10楼 nbic | 发表于 2007-05-28 12:29 |
| 初级用户 发帖 61 积分 135 | |
|
不错。。收藏学习。。
|
|
| 第11楼 long626201 | 发表于 2007-09-03 10:57 |
| 初级用户 发帖 52 积分 100 来自 云南 | |
|
谢了
|
|
| 第12楼 xyhs | 发表于 2007-09-03 20:24 |
| 新手上路 发帖 9 积分 17 | |
|
看了受益不少
|
|
| 第13楼 wordexport | 发表于 2007-09-29 15:05 |
| 初级用户 发帖 42 积分 87 | |
|
这么好的帖子,不顶还是人吗?
|
|
| 第14楼 wordexport | 发表于 2007-09-29 15:05 |
| 初级用户 发帖 42 积分 87 | |
|
向版主看齐
|
|
| 第15楼 austinfu | 发表于 2007-09-29 15:22 |
| 新手上路 发帖 1 积分 2 | |
|
let me see...
|
|
| 1 2 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |