[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
我在想,如果for是个函数的话,它大概分为几大子函数:无开关、/f、/l、/r、/d
而仔细回想一下,发现只要有无开关的for作为基础,就能降低其他几个开关实现的难度。
最有代表性的是for /l和for /f,举个例子
for /l %%a in (1 2 10) do echo %%a
::在这个(1 2 10)中,若不用变量通配替换,如何区分初始值、步数和终止点呢?若用for %%a in (1 2 10)...来判断呢?区分参数的工作一下轻松了许多

for /f "tokens=1* delims=:" %%a in ("123:345") do echo %%b
::for在这里如何去分别设置tokens=1* delims=:呢?我想,如果把无开关的for当成基石,那又降低了实现门槛:for %%a in (tokens^=1* delims^= do set %%a,值得一提的是,我原以为applda兄的那段代码之所以不需要加空格,是因为cmd在预处理时将参数划分好再加上空格(就像对重定向干的事一样),但是后来实验证明并非如此,对参数的划分是for命令(函数)自发的,仔细想想这也有道理,毕竟在cmd中,"tokens=1* delims=:"是以%2的形式传递给for命令(函数),cmd不会去解释参数中的参数,因为那在除了for以外的环境下都将是好心办坏事,所以for函数就和我们平时编写的函数一样,自己动手丰衣足食

TOP

16# zm900612

for确实是一个特别的命令,有一定的解释功能。

TOP

本帖最后由 zm900612 于 2011-5-26 19:55 编辑

引申话题:
既然for是函数,那别的内部命令又是什么呢?
看来也是函数咯?如果这个说法成立,那其他内部命令和for和if命令之间的区别是什么呢?

其实现在想来,完全把for和if当成函数的观点也有一点瑕疵,我举个例子:
  1. call for %%%%a in ("123") do echo %%%%a
  2. call if exist %0 echo 123
  3. pause
复制代码
显示的是“'XX'不是内部或外部命令,也不是可运行的程序或批处理文件。”,而别的命令则不存在此问题,这是不是说明cmd中其实并不直接存在for这个模块呢?

TOP

把以前的东西帖出来,先啥都不说,你们自己看,仔细看。(可怜以前没人参与讨论)
  1. -> type for.c
  2. #include <stdio.h>
  3. int main(int argc, char *argv[])
  4. {
  5.     int i;
  6.     for(i=0;i<argc;i++)printf("argv[%d]: `%s`\n", i, argv[i]);
  7.     return 0;
  8. }
  9. -> gcc -o for.exe for.c
  10. -> for.exe /f tokens^=1-3^ delims^=^" %a in ("a"b"c") do echo %a-%b-%c
  11. argv[0]: `for.exe`
  12. argv[1]: `/f`
  13. argv[2]: `tokens=1-3`
  14. argv[3]: `delims= %a in (abc) do echo %a-%b-%c`
  15. -> type for.bat
  16. @for.exe /f tokens^=1-3^ delims^=^" %%a in ("a"b"c") do echo %%a-%%b-%%c
  17. -> for.bat
  18. argv[0]: `for.exe`
  19. argv[1]: `/f`
  20. argv[2]: `tokens=1-3`
  21. argv[3]: `delims= %a in (abc) do echo %a-%b-%c`
  22. -> for.exe tokens^=1-3
  23. argv[0]: `for.exe`
  24. argv[1]: `tokens=1-3`
  25. -> test.bat tokens^=1-3
  26. %0: `test.bat`
  27. %1: `tokens`
  28. %2: `1-3`
复制代码
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

楼上貌似是for的模型?
可惜我不懂编程,只能大概地猜下

TOP

不是说for和if是“关键字”吗?难道是微软内部泄露出来的?
  1. -> type test.bat
  2. @prompt -$G$S
  3. echo a;echo
  4. for %%a in (a;echo) do echo a;echo
  5. echo for %%a in (a;echo) do echo a;echo
  6. rem if a;echo==a;echo echo a;echo
  7. if a==a;echo echo a;echo
  8. echo if a;echo==a;echo echo a;echo
  9. @echo\&pause
  10. -> test.bat
  11. -> echo a;echo
  12. a;echo
  13. -> for %a in (a echo) do echo a;echo
  14. -> echo a;echo
  15. a;echo
  16. -> echo a;echo
  17. a;echo
  18. -> echo for %a in (a;echo) do echo a;echo
  19. for %a in (a;echo) do echo a;echo
  20. -> rem if a;echo==a;echo echo a;echo
  21. -> if a == a echo echo a;echo
  22. echo a;echo
  23. -> echo if a;echo==a;echo echo a;echo
  24. if a;echo==a;echo echo a;echo
  25. 请按任意键继续. . .
复制代码
把分号换成逗号、等号效果一样。

可见预处理时对for、if的“参数”有特殊对待,会先把非空格分隔符统一处替换成空格。而for、if引导的命令中的分号、逗号、等号等不改变。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

本帖最后由 applba 于 2011-5-26 19:40 编辑

19# zqz0012005


虽然我没认真学过C,但是还是看懂了,这个对原理解释的比较透,但是有官方根据吗?还是自己想象出来的呢?或者是逆向的?

TOP

本帖最后由 applba 于 2011-5-26 20:38 编辑

运行前,cmd.exe对命令字符串进行一些处理,主要是特殊符号的解释。
还包括分辨出哪些是命令名,哪些是参数,具体依据是各种特殊符号(空格、逗号等分隔符)。

cmd.exe对一个“命令字符串”进行识别时,第一个空格之前的内容被识别为“命令名”。
例证:for^ /l %%i (1,1,5) echo %%i ,这里转义了第一个空格,结果运行提示
'for' 不是内部或外部命令,也不是可运行的程序或批处理文件。
第一个空格之后的剩余字符串,如果有可用的分隔符,会继续进行进行参数的分割。
如果使用了双引号或者^等转义了这些分隔符,第一个空格之后的所有剩余字符串会被当作一个整体参数传递。

for运行时,会再次识别这些转义后的特殊符号(空格,逗号等参数分隔符),并自行对他们进行解释(如参数分割)。
当然了如果上面一部的预处理已经分离出了全部或者部分的参数,下面不会重复进行分离。

for的自行解释过程是按照顺序进行的,首先看第一个空格后有没有 /开关,比如是for /f。
例子 for  /f delims^=^+   %%a in ("123+456")  do echo %%a
接着看下一个空格后是不是option,这个option必须是一个连续的字符串。
如果有空格,option会被分割,这个空格后的内容会被当作下一个参数。
但是for 此时只认为下一个参数只能是%%a,所以运行是提示 “此时不应有 *”。
如果有option中有空格或者其他特殊字符导致option被分割时,需要使用引号或者^来。

我觉得各个option之间的处理是通过关键字来判断的,即空格是是切割参数的,而不是切割option的
处理到option参数时,里面的空格会被丢弃。

处理完option之后,下一个空格后的内容只能是%%i,如果不是提示非法。
下一个空格后就是双括号了,再下一个空格之后就是do关键字了,如果不是提示非法……
下一个空格后就是具体的命令、语句或者语句块了,这个没什么好说的了……

%%i经过运行前的预处理,成为了%i,%i在for运行时被解释,即替换(或扩展)成具体的值。



同样call也能再次识别转义后的特殊符号,包括% ^和空格等。
只是call和for的解释机制有出入。

TOP

运行前的处理就是预处理。
从上面例子看for和if会影响预处理的。
再结合前一个例子,按一般理解,for /f 的 "usebackq skip eol tokens delims"等选项必须用引号引起来,可能就是为了让它整体作为一个参数传递给for“函数”(就象路径中有空格时也需要引号引起来),但可能因为预处理的特殊对待,不用引号也行,方法是对分隔符加^进行转义。但这种方法对其他程序无效,就像没转义一样,参数个数还是实际那么多。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

还有一个特殊的地方是
-> for.exe tokens^=1-3
argv[0]: `for.exe`
argv[1]: `tokens=1-3`

-> test.bat tokens^=1-3
%0: `test.bat`
%1: `tokens`
%2: `1-3`

同样的参数,程序和bat脚本竟然认为个数不同。而且不加转义符号结果一样。
看来是对合法分隔符的识别问题。
CMD会把分号、逗号、等号等都当作分隔符,但其他程序不这么认为。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

看得心慌,19楼的代码真的看懂了么?

那个for.exe命令行输入
  1. for.exe a=b=c x;,y 5678"\"\""" ....
复制代码
然后再输入
  1. for.exe /f delims=+ tokens=1-3 %a in ("fdf""dfd\"\"")do ^^echo %a
复制代码
体会下;

另外,cmd对代码预处理后的结果就是
在cmd开启echo on 后在屏幕上显示的结果;这个界定适合脚本也适合命令行;

我们看预处理做了哪些工作,用echo on的方法就行了,再做“批处理物理实验”就绕弯路了;

TOP

个人认为/f开关是for所有开关中最重要的一个,对于新手甚至部分老手要掌握这个/f开关的所有参数及其用法是有一定难度的。。。

关于eol,usebackq,skip,tokens,delims这五个/f开关下的参数,记得cn-dos的9527有一篇 ...
batman 发表于 2011-5-25 19:30

基于for的参数不需要空格分隔的理论基础,老兄这说法也大有问题,而且哪怕用上空格来分隔,似乎也不惧:
  1. @echo off
  2. for /f "delims=, tokens=1,2 eol=e skip=1" %%a in ('
  3. "echo skip&echo eol&echo 显 示,不显示"
  4. ') do echo %%a
  5. pause
复制代码
该显示的仍然显示了,不该显示的也同样没有显示,并不因为“delims=,”后跟空格而造成误判。看来for对于参数的划分有点像cmd对于重定向的划分,虽然在cmd回显中看不到,但是我想,for对参数的划分应该也是和cmd同样的从预处理到执行的步骤:
1、转换分隔符为空格,如果不存在分隔符则自动加上空格(就像cmd会把“echo>nul 不显示”预处理成“echo 不显示 1>nul”一样)
2、读取参数#@!@@#¥!……

另外,顺便提一个疑惑,如果for真的是函数,如何解释for在语块中不能对其参数使用带有延迟性质的变量呢?

TOP

要说的是,那段c代码跟cmd的for完全没关系,只是一段再普通不过的代码,打印出所有的命令行参数。
只是为了试验对分隔符转义后,可不可以让多个参数被整体当作成一个参数。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

命令行的POSIX规范:
以一个横杠开头的为选项。
如果不带参数的话,多个选项可以写在一个横杠后面。如-abc与-a -b -c的含义相同。
选项名是单字符的英文字母或者数字。
某些选项是带参数的。
选项和它的参数既可以分开写也可以在一起,grep选项中的 -A 10 与 -A10都是合乎规范的。
选项参数写在非选项参数之前。
如果一个参数只是两个横杠--,那么它会结束所有的选项,所有跟在它后面的参数都被视作非选项,即使它们前面有一个横杠。
一个单横杠-被解释为普通的非选项参数,通常它用来表示对标准输入和输出流的输入或者输出。
选项之间可以是任意顺序,也可多次出现,由程序负责对此进行解释。

微软似乎喜欢和POSIX对着干。
Windows下满足这一规范哪怕是其中几条的命令寥寥无几,xcopy、findstr等命令的参数可以写在一起,这样看来for /f 勉强也算上吧。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

23# applba


我总结一下:
运行前的预处理,如果有可用的(即没有被转义)分隔符(如空格、逗号等)是会进行参数分割的。
如果没有可用分隔符,把第一个空格后的所有字符串作为一个整体参数传递。
这个过程是cmd .exe来完成的。

有些命令运行时会再次识别转义后的特殊字符,并再次启动解释工作。
比如call会再次识别转义后的%、^、空格等。
for也会再次识别转义后的空格等

TOP

返回列表