[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
看了下,挺不错。不过少量说法比较表面化,可能对预处理的理解还不够到位

TOP

6# qzwqzw

cmd少一层预处理...

TOP

我理解的批处理优先级如下,从上到下按从高到低排序:
%1
%
()                         【没被转义的括号是语块的划分符号,所以for命令和if命令其实本质应该不是语句,而是语块】
&和|和&&和||
>和<
%%a                   【执行时,因为%%已被转义,所以其实执行的是%a】
空格以及他分隔符
"和^                     【for /f中的“"”存在特例,对此我也不是很理解】
!

不知道还有没有漏的

TOP

而call echo %%a%%的实质大概是它运行的是cmd /k echo %%a%%
此时在父cmd中进行了第一级预处理,变成cmd /k echo %a%,然后在子cmd中再解释变量a,由于子进程继承了父进程的变量环境,所以变量a能够被成功地延迟扩展。
值得一提的是,call命令对for命令和if命令似乎没辙,我到现在为止坚持认为for命令和if命令是最特殊的两个命令,因为它们都包含着语块,典型的例子是for,for命令的输出和输入都是语块,这是别的命令做不到的,虽然cmd命令也有“cmd /c "语句一&语句二&语句三"”这种类似于语块的用法,但其实现执行语块的本质还是将语块作为参数传递给子cmd。所以我猜测call命令可能无法解读语块,具体原因不明。

TOP

14# qzwqzw


有道理,我武断了

TOP

21# applba


有的,测试过的了。
不过先前没注意到的是,不管有多少层call,似乎只创建了一个新cmd进程,看来还有猫腻

TOP

发现call ping不像call pause,真的没有多余进程

TOP

明白了,pause是内部命令

TOP

17# zm900612


不记得谁说过:
for和if是高级语句,相当于一个命令解释器,他们能独立的对后面的语句块进行解释……
applba 发表于 2011-5-18 01:13

确实,这个看法比我的观点更明晰准确,看来我以后要改口了

TOP

31# hucuibai


用非常非常拐弯抹角的方法设为变量
http://bbs.bathome.net/viewthrea ... muid=30406#pid78640

TOP

37# applba


命令行的特点是从上到下、从左到右

TOP

35# qzwqzw


我也这么认为,前面被那个比较有条理的说法吓倒了...仔细想想for和if确实是语块,比如:
  1. @echo off&setlocal enabledelayedexpansion
  2. set "a b=."
  3. set "tmp=a b"
  4. echo for内:
  5. for %%a in ("a b") do if defined %%~a echo 存在“a b”
  6. ::正确
  7. echo;&echo 不使用变量延迟:
  8. (if defined a b echo 存在“a b”)
  9. ::出错
  10. echo;&echo 变量延迟:
  11. (if defined !tmp! echo 存在“a b”)
  12. ::正确
  13. echo;&pause
复制代码
我原来一直以为if defined是不支持空格变量名的,直到某天在某群里某个自以为是的家伙误打误撞写出来,我原以为会出错,结果一运行竟然没问题,这才发现原来if的条件语句是和整个语块一起进行划分的,也就是说,if不是一个语句,而是语块,for也是同样的情况,最有说服力的就是for循环中的for命令的开关、选项和参数是无法直接用变量修改的,这也证明了在语块划分完毕的时候,for语句的条件语句之前的部分也已经划分完了:
  1. for /f "tokens=!a!" ...
复制代码
众所周知这是会出错的
还有:
call if ...
call for ...
这两个都会出错,从错误提示来看,只能说明,for和if完全不是普通语句,而更可能是语块

TOP

36# hucuibai
恰恰相反,|的优先级高于&

from verybat(怀念之):
'%' >> '^' > '()' > '>、>>' > | > & > && > ||
%是顶级优先处理的,所以用“远远大于(>>)”

预处理时要判定语句的结构和功能。

当时zq ...
powerbat 发表于 2011-5-19 22:06


'>、>>' > | > & > && > ||?
重定向的优先级应该排在语句的连接符之后吧

TOP

以前不是有人说过for和if是“关键词”吗?

set n=3&for /l %%a in (1 1 !n!) do ...
是没问题的。
set n=3&for /l %%a in (1 1 !n!) do (... if %Got%==1 (set n=10) ...)
在循环体中改变循环条件是不行的。
powerbat 发表于 2011-5-19 22:24

如果for和if是语块这个命题成立,那么条件语句将是语块的一部分,而非语句的一部分,这就可以解释为什么在语块中无法重新定义for和if的条件语句了,因为它们的条件语句是和整个语块一起被预处理的

TOP

46# qzwqzw

|  > >> < & && ||
这几个特殊符号肯定是在执行时进行功能解读的,前四个都涉及到句柄,后三个都必须等待前面的命令执行完毕。

你的说法也合理:即这几个符号那个在前面就先处理哪个,前面的先处 ...
applba 发表于 2011-5-20 00:48


|是兼具句柄重定向和语句连接符功能的,而且具有连接符所有特征,所以不能将它和重定向符号并列起来。我举个例子
  1. (dir >1.txt >con)>2.txt
  2. ::重定向符号是并列的,但是每一次重定向都会刷新对应句柄的设置,所以对同样的句柄,只有最后一次重定向是有效的。
  3. set|findstr /i "pro"|sort +2
  4. ::而管道则不光将两个命令的0、1句柄桥接起来,还充当了语句之间的连接符,连接符的特征是按从左到右的顺序进行判断,举个例子:
  5. 2>nul ren %~s0 &&(echo 1,此处不显示)||(echo 2,此处显示)&&(echo 3,此处显示)||(echo 4,此处不显示)
  6. ::可见语句的优先级顺序就是连接符的优先级顺序,连接符是并列的,而且优先级高于重定向符。
  7. pause
复制代码

TOP

返回列表