标题: 批处理中的for命令原理图示 [打印本页]
作者: myzwd 时间: 2009-3-2 13:21 标题: 批处理中的for命令原理图示
- @echo off
- for /l %%1 in (0 1 2) do (
- set x=%%1
- call,echo %%x%%
- pause >nul
- echo ok
-
- )
复制代码
上述代码运行显示如下----
0
暂停
ok
1
暂停
ok
2
暂停
ok
---------------------------
网上看到不少关于call echo的说法的,最多的说法是,脱%论。但我觉得,脱%论,应该算是语法的范畴,与for的运行原理无关。那只是表象。也许你会说堆栈是后进先出,是的,你注意没有,for中堆栈里面始终就只有一个数据。这让我明白了。延迟环境变量,就是启用堆栈。
我认为----call echo是----call ,echo的简写,其运行原理应该与堆栈有关。“call ,echo”就是用了空标号原理。
那么空标号成立吗?
你验证下面的代码吧:- @echo off
- echo ok 1
- call ,
- echo ok 2
复制代码
这点和setlocal enabledelayedecpansion的原理相同。下面把for 。。。call echo的流程图示如下:
----------------在讨论中进步------错对不重要 重要的是参与-----争取每天都有一点点收获------------------------------------------------------------------------------
从for想到的 再解释机制--在此提出共商讨--
观点如下
1---cmd是以解释方式执行命令的,即机器翻译一条,执行一条,如此反复,直到完成程序。
2---cmd在解释程序中的一条(注意是一条)语句时,一定是,一定是!!!预先把语句中的数据匹配好之后,
才开始执行。
3--如果是一个语句块,里面又有语句块,cmd就会对小语句块再做出解释。这就是我的观点。
4--实例分析:
我----
@echo off
set tt=123
if 2==2 (
set tt=222
echo %tt%
call echo %%tt%%
)
分析:这里就是语句块套语句块,cmd在解释if语句时,遇到里面的小语句块call echo %%tt%%,
就对它进行再解释。当这些解释都完成后,cmd才算就完成了对if语句的解释。最后执行if语句。
显见call只会抓取离它最近的set变量数据。这样就说明了if体内数据为什么会变。
的---
@echo off
set tt=123
for %%1 in (0 1 2) do (
set tt=222
echo %tt%
echo %tt%
echo ----------
)
分析:我认为的理由同上---语句块套语句块,为了数据的匹配,for对子语句块做出再解释。
5---延迟变量
我的观点是开启延迟变量后,就推迟(延迟)for主语句体的执行,因为,cmd要再次解释
for体内部的延迟变量!tt!,再解释是要花费“时间”的,for的执行就被推迟了。所以就叫
延迟了。在解释for体内的!tt!变量时,这个变量总是抓取离它最近的set 所定义的值。
关----
@echo off
setlocal enabledelayedexpansion
set tt=123
for %%1 in (0 1 2) do (
set tt=222
echo %tt%
echo !tt!
echo ----------
)
这样看来"echo !tt!" 。被再解释了。
[ 本帖最后由 myzwd 于 2009-3-3 15:24 编辑 ]
作者: lhjoanna 时间: 2009-3-2 21:03
楼主的图画的很晕啊,不过我还是细细的看了一遍。提出几个疑问:
<1>call空标号的说法有何依据?空标号原理是什么?
<2>上面提到的堆栈是用来存放什么数据的?for堆栈又指什么?
<3>"延迟环境变量,就是启用堆栈"又有什么根据?
我的看法:
<1>对于上述例子中的call , 可以运行的情况。楼主认为是空标号。既然是空标号,楼主又加个逗号是何意?加了逗号还是空标号吗?我测试过call后加空格,逗号,分号都可以正确运行。并且空格,逗号,分号都是批处理的分隔符。for对文本或文件解析时delims默认为空格和逗号,eol默认为分号。并且使用call做调用子程序用时都需要加冒号的。
<2>楼主说call,echo %%x%% 时,首先把0入栈,然后发觉是空标号,所以就又出栈。这样做有何意义?换个角度,从底层来看,每次调用子程序过程中,call包含两层意思:首先把当前指令的段地址与偏移地址入栈,其次执行跳转指令,也就是跳转到标签所在的地址。并且子程序结束后会有一个 goto :eof,表示子程序结束。这个goto :eof也就是之前入栈的地址出栈,程序接着上面调用子程序的下一条执行。由此看来,入栈的原因是保护现场,需要入栈的是指令的地址,而不是程序需要处理的数据。
<3>"延迟环境变量,就是启用堆栈",这样的说法我头一次听说。对于for中遇到开启变量延迟的变量就入栈的说法,不知具体有什么思考、根据。
<4>我想这又涉及到一个call与变量延迟机制的问题,想要完全弄明白还需要从机制入手。对于楼主的行为我表示肯定,我想这也会吸引更多的人来参与讨论的。一个新理论的提出确实需要来自多方面的检验。
附:一个简单的例子,就是查看开启变量延迟和使用call后的执行时间对比。
- @echo off&setlocal enabledelayedexpansion
- set str=123
- echo %time%
- for /l %%i in (1,1,10000) do echo %str%>nul
- echo %time%
- for /l %%i in (1,1,10000) do echo !str!>nul
- echo %time%
- for /l %%i in (1,1,10000) do call echo %%str%%>nul
- echo %time%
- pause
复制代码
作者: myzwd 时间: 2009-3-2 22:36 标题: 回复 2楼 的帖子
这中间 需要讨论的太多。还望大家参与。无论错对,都会提高对for和延迟变量的认识。你的代码我运行了,时间不一样,call明显的慢,但这说明不了数据的流程啊- @echo off
-
-
- setlocal enabledelayedexpansion
- echo %time%
- for /l %%i in (1,1,500) do echo 111>nul
- echo %time%
- endlocal
- pause
-
- echo %time%
- for /l %%i in (1,1,500) do call echo 111>nul
- echo %time%
- pause
复制代码
延迟块的原因是我猜是没有set变量在for体内的传递。
我突然想起了call echo这个结构看起来多象调用外部的批处理啊。---批处理函数。对就是它
@echo off
call mybatchfilesname
goto:eof
------------------
外部文件
----mybatchfilesname.bat-
echo 123456789
----------------------------
这个call echo中的echo不就相当与外部的批文件吗,调用外部的文件当然要慢点啊
这更能证明是堆栈的原理了。调用外部文件可以跟参数,call echo后面可以跟环境变量,这中间是什么关系呢?晕。
你们的论坛真的不错。我来这里是学习的,以前我没想到批处理可以编制那么好玩的程序。来这里我学到了不少东西。
[ 本帖最后由 myzwd 于 2009-3-2 23:42 编辑 ]
作者: lhjoanna 时间: 2009-3-2 23:09 标题: 回复 3楼 的帖子
恩,楼主也说了,call明显速度变慢。这也就是我说的意思,这就引出一个疑问:为什么会变慢?call echo的机制是什么?
作者: zqz0012005 时间: 2009-3-2 23:25
楼主不会是联盟的5yue5吧。
http://www.cn-dos.net/forum/viewthread.php?tid=46415
作者: Batcher 时间: 2009-3-2 23:33 标题: 回复 5楼 的帖子
看到“堆栈”二字的时候,我也是这样联想的^_^
作者: irresolute 时间: 2009-3-4 08:14 标题: 随便说二句
call,echo %%x%% 豆号其实就是分隔符,可改为空格,call也具有变量延迟的功能。
作者: wbh 时间: 2010-8-27 08:27
我找到了答案 关于CALL 的用法,请参考http://ss64.com/nt/call.html
关于 FOR 命令中CALL 的用法,请参考http://www.dostips.com/DtTipsFtpBatchScript.php#Batch.FtpBatchUsingVariables
都是英文的,我已经翻译成了中文,请参考http://hi.baidu.com/wangbaohua3/blog/item/bdba8f66be4cefd3e6113a60.html
作者: zhlg9782 时间: 2010-10-7 19:28
看看!
作者: ai20110304 时间: 2018-8-28 15:24
回复 8# wbh
谢谢分享这么好的网站
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |