标题: 猜想for的预处理过程,有误之处,请帮忙指出,谢谢!
[打印本页]
作者: maky1117
时间: 2008-11-24 19:41
标题: 猜想for的预处理过程,有误之处,请帮忙指出,谢谢!
本帖讨论的主要内容跟变量延迟有密切关系,初学者建议先参考以下连接:
变量延迟详解
http://www.cn-dos.net/forum/viewthread.php?tid=28273
什么情况下该使用变量延迟
http://www.cn-dos.net/forum/viewthread.php?tid=20733
一个变量嵌套变量的问题
http://www.cn-dos.net/forum/viewthread.php?tid=41143
废话不说,直接切入主题:
先上一个我的测试p:
for /l %%j in (1,1,10) do (
set x=%%Down%%j%%
pause
)
不要多次一举添上@echo off,否则就看不到执行过程

我添加一个pause,意在只分析第一个循环(一共十个,不加的话,后果自负

)
执行后分析会发现for被拆成两条“语句”来执行
++++++++++++++++++
for /l %j in (1,1,80) do (
set x=%Down%j%
pause
)
++++++++++++++++++
(
set x=%Down1%
pause
)
++++++++++++++++++
(上述叙述有不懂的,请亲自运行p看结果)
根据变量延迟的原理,即cmd预处理机制,cmd会把读取的每一条语句进行预处理,遇到%%的内容会进行扩展(除非你把cmd扩展功能关了),上一个题外的例子,帮助大家理解:
set a=1234567890abcdefg
set b=4
set c=5
echo %%a:~%b%,%c%%%
call echo %%a:~%b%,%c%%%
pause
这种代码经常被拿来吓唬新手,其实有更加简洁的方式(没错,就是用!!,具体实现自己动手做),其实还是有规可循的,别眨眼,看cmd预处理步骤:
当cmd读到echo %%a:~%b%,%c%%%这一句时(哼,穿这么多%%充胖子?剥!

)
剥完就变成echo %a:~4,5%
(%%被剥成%,%b%和%c%只穿一件%%,剥完就原形毕露了

)
于是echo %%a:~%b%,%c%%%的结果就是%a:~4,5%啦,你会问%a:~4,5%不是一个标准的变量参考吗?结果怎么不是56789?这里卖个关子,请接着看下一句call echo %%a:~%b%,%c%%%,有经验的别闲着,赶紧动手剥!
call echo %a:~4,5%,跟上句差不太多,就多一个call。嘿嘿知道为什么卖关子了吧?这句结果正是56789,因为call的作用是再剥一层,剥完%%之后就得到真正想要的结果了。
回归正题,我猜想
for /l %%j in (1,1,10) do (
set x=%%Down%%j%%
pause
)
剥后得到:
for /l %j in (1,1,80) do (
set x=%Down%j%
pause
)
然后再剥得到:
(
set x=%Down1%
pause
)
停!看这里,是不是感觉有些怪怪的?望眼欲穿都只看出%j=1这个赋值的关系吧?

对,就我目前的猜想也是如此,第二个语句没有“剥”事件发生,是纯粹的赋值行为。大家可以添加%%来验证结果。
我的猜想结论是:for先被cmd预处理“剥”了一层%%,随后进行的循环只是赋值,不再进行“剥”的行为,要“剥”请自行添加call或setlocal!!
PS:由于本人比较懒,for语句例子摘自
http://www.cn-dos.net/forum/viewthread.php?tid=24418,这是一个很棒的学习例子,给了我不少灵感和启发
[
Last edited by maky1117 on 2008-11-24 at 19:42 ]
作者: HAT
时间: 2008-11-24 20:28
参考:预处理究竟是如何进行的
http://www.cn-dos.net/forum/viewthread.php?tid=43905#pid305954