Board logo

标题: [原创] 批处理常见问题解答 [打印本页]

作者: namejm    时间: 2008-7-12 14:52     标题: 批处理常见问题解答

1、Q:我在网上发现了一段批处理代码,要怎样处理才能使它运行起来?
  A:批处理是解释型脚本语言,只需把代码复制下来,保存为以.bat或.cmd为后缀名的文件即可运行。不过,文件名最好不要和命令名重合,比如,不要保存为if.cmd、for.bat、set.cmd等文件;

2、Q:我在几乎每段完整的批处理代码第一行都发现有 @echo off 这条语句,请问这是什么意思?可以不要吗?可以把它放到其他位置吗?
  A:@echo off 的含义是:当批处理文件运行的时候,不在屏幕上显示每条语句;如果没有这条语句,那么,批处理文件中每一条将要执行到的语句,都会被显示在屏幕上。因为批处理在执行的时候,或多或少都会在屏幕上显示各种执行结果,如果去掉这条语句,那么,在默认情况下(没有重定向语句的时候),语句本身和执行结果都会显示在屏幕上,显示结果将十分混乱和繁杂,一般而言,这并不是我们需要的效果,这个时候,就需要在批处理文件的第一行写上 @echo off 这条语句;当然,@echo off 语句并不是必须的,在某些时候,我们并不需要它,比如,当我们调试代码的时候,一般都会去掉 @echo off 语句,再在适当的位置添加暂停命令pause,观察执行结果并定位出错位置;@echo off 语句可以放在任意位置,但是,只有在它之后的语句本身才不会显示在屏幕上。

3、Q:%var%中的百分号对是什么意思?!var!呢?
  A:百分号对表示对变量值的引用,换句话说,%var% 在代码执行过程中,将会被变量var的具体值替换。假设 set var=abc,那么,%var% 就表示 abc 这个字符串;!var! 也是同样的含义,只不过,感叹号对是在启用了变量延迟之后才使用的。关于变量延迟的具体含义,请参考下一条。

4、Q:经常看到 setlocal enabledelayedexpansion 这条语句,这是什么意思?在什么场合下使用?
  A:setlocal enabledelayedexpansion 表示它之后的代码启用了变量延迟功能,此时,对变量的引用不再使用百分号对的格式,而是采用感叹号对格式,即用 !var! 格式替换 %var% 格式。具体含义请参考以下解释:
转自中国DOS联盟:http://www.cn-dos.net/forum/viewthread.php?tid=20733
关于环境变量延迟扩展,使用set /?可以查看到部分说明,不过考虑到其粗劣的翻译水平,建议在查看之前,首先chcp 437切换为英文查看原英文说明。鉴于文中已说得十分详尽,而且有数个代码示例,应该不难理解。在此仅略作一些补充。

      在许多可见的官方文档中,均将使用一对百分号闭合环境变量以完成对其值的替换行为称之为“扩展(expansion)”,这其实是一个第一方的概念,是从命令解释器的角度进行称谓的,而从我们使用者的角度来看,则可以将它看作是引用(Reference)、调用(Call)或者获取(Get)。

      而命令解释器是扩展环境变量的行为大致如下:首先读取命令行的一条完整语句,在进行一些先期的预处理之后,命令被解释执行之前,会对其中用百分号闭合的字符串进行匹配,如果在环境空间中找到了与字符串相匹配的环境变量,则用其值替换掉原字符串及百分号本身,如果未得到匹配,则用一个空串替换,这个过程就是环境变量的“扩展”,它仍然属于命令行的预处理范畴。

      而一条“完整的语句”,在NT的命令解释器CMD中被解释为“for if else”等含有语句块的语句和用“& | && ||”等连接起来的复合语句。

      因此,当CMD读取for语句时,其后用一对圆扩号闭合的所有语句将一同读取,并完成必要的预处理工作,这其中就包括环境变量的扩展,所以在for中的所有语句执行之前,所有的环境变量都已经被替换为for之前所设定的值,从而成为一个字符串常量,而不再是变量。无论在for中将那些环境变量如何修改,真正受到影响的只是环境变量空间,而非for语句内部。
      
      而为了能够在for语句内部感知环境变量的动态变化,CMD设计了延迟的环境变量扩展特性,也就是说,当CMD读取了一条完整的语句之后,它不会立即执行变量的扩展行为,而会在某个单条语句执行之前再进行扩展,也就是说,这个扩展行为被“延迟”了。

      延迟环境变量扩展特性在CMD中缺省是关闭的,开启它的方法目前有两个:一是CMD /v:off(此处说法有误,应为 CMD /v:on——namejm 注),它会打开一个新的命令行外壳,在使用exit退出这个外壳之前,扩展特性始终有效,常用于命令行环境中;二是setlocal EnableDelayedExpansion,它会使环境变量的修改限制到局部空间中,在endlocal之后,扩展特性和之前对环境变量的修改将一同消失,常用于批处理语句中。

更加通俗的解释请参考这个帖子:http://www.cn-dos.net/forum/viewthread.php?tid=28273

5、Q:goto :eof 是什么意思?在什么情况下使用?
  A:① 如果定义了 :eof 标签,则单独的 goto :eof 表示跳转到标签段 :eof,此时,goto :eof 等同于 goto eof;用于 call 语句子过程中的 goto :eof 表示跳转到此批处理文件的末尾(后一种情况由 随风 补充)
    ② 如果没有定义 :eof 标签,则表示跳转到当前批处理文件的末尾,此时, eof 的含义是 end of file ,这是批处理中 goto :eof 的默认用法。这一语句常用于 call 语句的子过程中。例如如下代码:
  1. @echo off
  2. call :test1
  3. call :test2
  4. call :test3
  5. goto :eof
  6. :test1
  7. echo 这是第一个标签
  8. pause
  9. goto :eof
  10. :test2
  11. echo 这是第二个标签
  12. pause
  13. goto :eof
  14. :test3
  15. echo 这是第三个标签
  16. pause
  17. goto :eof
复制代码
如果某个标签段没有goto :eof,则该 call 语句调用子过程时,子过程将在第一个 goto :eof 出结束;如果没有任何 goto :eof 语句,call 语句将从该子过程的第一句开始执行,直到文件末尾处结束;如果 goto :eof 不是出现在 call 语句调用的子过程中,则直接跳转到批处理文件末尾,此时将退出批处理程序,功能和 exit 命令等同,如以上代码中的第5行,只有在这个时候, goto :eof 才可以用 exit 替换。
作者: wc726842270    时间: 2010-11-27 20:48

感觉不错,顶一下,看来看的人很少,但不会的却不少
作者: rockets    时间: 2010-12-1 17:32

默默的踩一下~~~~~
作者: sohu    时间: 2010-12-2 10:25

历久弥新。。。。。。。。。。。。。。。。。。。。。。。。。。。
作者: acaigg    时间: 2011-1-12 19:42

学习一下。支持一下。
作者: Hello123World    时间: 2011-5-20 12:33

子过程将在第一个 goto :eof 出结束——处结束。一个错别字,原来你也是玩拼音的啊!
作者: Hello123World    时间: 2011-5-20 12:42

原来goto :eof 可以用来结束子过程。
作者: lxin    时间: 2011-6-2 12:22

受教了,感谢楼主的分离,谢谢
作者: andy七少    时间: 2011-6-9 12:42

这都是需要注意的问题,谢谢lz分享
作者: bawed    时间: 2011-6-9 14:12

100 :victory: 不错
作者: tangqingfu    时间: 2013-5-28 21:31

谢谢分享,学习ing……
作者: ai20110304    时间: 2018-6-10 22:48

好文章。受益匪浅




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2