[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
楼主的说法问题很大啊:
1、批处理不是事先读取整个文本,而是逐行解释、逐条执行
2、对 % 的预处理高于一切,它和 "、^ 完全不在一个重量级上

以下转自别处【】内是我补充的:
  1. cmd 执行一个批处理中的语句时是按照这样的流程进行的:
  2. 1、cmd 调用 shell 解释参数变量【%0~%9】、同时对 %str% 这种普通的变量形式进行解释【同时将单独的 % 作为自身的转义符看待,这三者是平级的,具体怎么预处理要看出现的次序】
  3. 2、切分语块、操作【语块的】句柄(如果存在针对语块的句柄的话)
  4. 3、划分语句,同时将参数分隔符转换为空格,并把有效的重定向(句柄操作)后置
  5. 4、当一个语句中存在使用了变量延迟的变量 !str! 时,将会被进行一次额外的针对转义符 ^ 和 !str! 的预处理
  6. 5、操作【单条命令的】句柄
  7. 6、执行语句
  8. 7、释放句柄
复制代码

TOP

得到这些结果实在太震撼了…
颠覆了固有的思想,CMD竟然边预处理边找新行
我感觉继续往下挖掘,CMD会有更多更奇怪的事情被我们发现
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

本帖最后由 defanive 于 2011-8-23 05:00 编辑

()的分组对预处理的影响
:标签的处理优先级
命令行参数去掉%0的规则
setlocal enableextensions会开启新的变量块,但是是否每次调用就开启一次新的
for的循环变量%%x处理问题
句柄操作的解释优先级
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

本帖最后由 defanive 于 2011-8-23 04:54 编辑

在顶楼的帖子里面部分明确,但有不同意的地方

关于每次都重新读取批处理文件:
我认为批处理每执行一次就会重新读取一次批处理文件,如下例
先将批处理内容写为
@echo off
pause
运行批处理,在暂停的时候将批处理改为
@echo off
pause
pause
回到CMD按任意键后可以发现出现了按任意键继续的提示,说明CMD重新读取了一次批处理文件

关于不是分行读取批处理:
平常我们都认为CMD是一行一行读取批处理后分别处理并执行的
我认为CMD是从文件标记处开始一直读取,找到下一个合法的换行符之后设置文件标记并执行
下例说明了CMD不是分行读取并分行执行的
@echo off
echo a^
b
pause
此处充分说明了不是分行读取的,因为若是这样的话^号没有转义目标直接显示出a
下例说明CMD是以设置文件标记的方式往下运行的,先将批处理内容写为
@echo off
pause
echo 123
pause
然后运行批处理,在暂停的时候将批处理改为
echo off
pause
echo 123
pause
然后回到CMD并按继续,可以发现提示'cho'不是内部或外部命令
此例充分说明了CMD是以设置标记的方式读取的
运行到第一次pause时设置的标记是在文件的第18字节处(即是echo 123的开始),但是我们在运行时将@去掉使得文件往前移动了1字节,即此时第18字节对应的是cho 123,必然出现错误信息

关于边预处理边找新行、三个符号%^"实际是同时预处理:
平常认为是CMD找到了分行之后再进行预处理,我认为预处理与找新行是同时进行的
@echo off
set "a=^"
echo a%a%
b
pause
上例说明了预处理与找新行是同时的
因为如果是找到新行再进行预处理,则必然会显示a和'b'不是内部和外部命令
而事实是在找新行之前已经把%a%替换成了^号,并且^号把下面的回车换行符转义了,因此会继续寻找到pause之前,显示出ab
同时这也说明了%、^、"这三个符号是同时进行预处理,而不是像顶楼帖子所说的“先预处理完%,再进行^与"的并行预处理”
因为如果是先处理完%的话,此时^号并没有预处理,则回车换行符没有被转义,那么仍然应该显示a和'b'不是内部和外部命令
但事实是显示了ab,说明在替换完%之后,则同时继续进行了^和"的预处理
顶楼的帖子说明了这三者的优先级顺序,%总之处于最高优先级,"和^处于并列优先级
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

本帖最后由 defanive 于 2011-8-23 04:26 编辑

未完成
PS:还有一些可以写的,困了跑去睡觉了

//主循环
//文件标记为0
{
  从标记处开始读取文件到结尾
  //第一步预处理
  {
    //处理%,^,"
    读取的内容从头至尾遍历
    {
      判断下一个字符
      {
        是%:
          判断%内解析标记
          {
            为真:
              将上一个%到本个%的内容为变量名,查找变量名。找到则替换为变量内容,未找到则将上一个%到本个%的内容丢弃
            为假:
              判断下一个字符
              {
                是数字:替换为单个命令行参数,即处理%0~%9的情况
                是*:替换为除%0命令行参数
                是~:继续判断是否合法,到不合法时终止。终止后,判断最后一位是否是数字,若是则替换为单个命令行参数
                是%:丢弃当前的%,保留下一位
                其他:设置%内解析标记为真
              }
          }
        是^:若%内解析标记为假,则转义下一个字符
        是":若%内解析标记为假,则转义字符直至下一个"
        是回车换行符(连续两个内容为0D0A):
          设置文件标记为0D0A之后
          执行代码
          中断本次循环,回到主循环
      }
    }
  }
}
第三方命令行工具编程
Http://Hi.Baidu.Com/Console_App

TOP

返回列表