找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 44228|回复: 13

[其他] 批处理中start与call的用法的区别是什么?

[复制链接]
发表于 2010-12-13 21:01:40 | 显示全部楼层 |阅读模式
start与call的用法的区别?
发表于 2010-12-13 21:17:11 | 显示全部楼层
call的最大特点是可以调用本批内的标签,继承父批的环境变量,返回时带着子批的环境变量,start不能。
 楼主| 发表于 2010-12-13 22:16:22 | 显示全部楼层
有点抽象,能否举个例子说明一下?我接受批处理的时间不长,还只是个菜鸟。
发表于 2010-12-13 22:25:40 | 显示全部楼层
  1. @echo off
  2. set a=123
  3. call:han 789
  4. echo 来自call的变量:%b%
  5. pause&exit
  6. :han
  7. echo 参数%1
  8. echo 变量a可以在这里用:%a%
  9. set b=456
复制代码
发表于 2010-12-14 00:04:14 | 显示全部楼层
说实话个人认为LZ还是先了解一下START。CALL这两个命令的基础比较好,至于区别即使给你答案,也会事半功倍
如果想暂时的了解一下参考下http://www.bathome.net/viewthrea ... amp;highlight=start
另外论谈的搜索功能也是非常的强大,有什么不明白的地方,这应该是首选
 楼主| 发表于 2010-12-14 11:17:03 | 显示全部楼层
通过4楼的例子,还有5楼提供的参考,我对start与call的区别有了进一步的了解,谢了!
发表于 2011-5-23 18:43:36 | 显示全部楼层
请问一个批处理a.cmd可以直接调用另一个批处理b.cmd内部的标签:sub吗?
发表于 2011-5-23 18:56:00 | 显示全部楼层
7# applba


据我所知,直接调用的好像没有
发表于 2011-5-23 19:20:36 | 显示全部楼层
比如我把很多常用的子过程或者函数放到一个批处理里面。

然后我这样调用 call b.cmd "sub 123"

sub是子过程,123是参数
发表于 2011-5-23 19:30:11 | 显示全部楼层
比如说子过程库(标签以/开头)文件为sos.cmd
添加“文件头”:
  1. @(
  2.   if "%~1"=="/plp" (
  3.         call:%2 %*
  4.   )else call:%*
  5.   goto:eof
  6. )
复制代码
然后 sos/子过程标签 参数列表

我的库函数就这么搞的。。。当然不一定必须这么搞,,只是个思路。。。

评分

参与人数 1技术 +1 收起 理由
applba + 1

查看全部评分

发表于 2011-5-23 22:06:04 | 显示全部楼层
10# plp626
怎么觉得楼上的用法如此怪异
原来是@()的在作怪

在call 不支持直接调用标签的时候
那时是MS-DOS为王的时代
就已经有了标准调用内部或外部的标签的做法
基本上采用下面的形式

1.简单的基本用法
@echo off
if [%1]==[$] goto %2

:sub1
rem some code
goto :end

:end

调用的时候采用
call %0 $ sub1
外部调用采用
call lib.bat $ sub1

2.在需要传递参数的时候
@echo off
if [%1]==[] goto :end
shift
shift
goto %0

:function1
echo %1+%2+%3
rem some code
goto :end

:end

调用的时候采用
call %0 $ func1 arg1 arg2 arg3
外部调用采用
call lib.bat $ func1 arg1 arg2 arg3

3.在需要返回结果值的时候
@echo off
if [%1]==[] goto :end
shift
shift
goto %0

:func2
rem some code
set _ret=%2-%1-%3
goto :end

:end

调用的时候仍然采用
call %0 $ func2 arg1 arg2 arg3
外部调用也是采用
call lib.bat $ func2 arg1 arg2 arg3
只不过多了使用 %_ret% 引用返回结果的语句罢了

4.到了WinNT时代
cmd功能强了限制少了
Call可以直接调用内部标签了
shift移位可以保留%0了
命令行参数也可以增强扩展了
标签名不再限制8个字符长度了
不过基本思想变化不大

@echo off
if [%1]==[$] shift/1&shift/1&goto %2

:function
rem some code
set _ret=%2-%1-%3
goto :end

:end

调用的时候仍然采用
call %0 $ func2 arg1 arg2 arg3
外部调用也是采用
call lib.bat $ func2 arg1 arg2 arg3

5.当然对于要求不严格的场合
用if not [%1]==[] goto %1跳转标签也是可以的
发表于 2011-5-23 22:13:57 | 显示全部楼层
本帖最后由 plp626 于 2011-5-23 22:18 编辑

11# qzwqzw


%1 %2 。。。
这样最多也就支持9个,如果shift要goto费时。。。而且在预处理时会把参数分隔符比如等号,逗号,分毫给吃了。。

为了参数原样传递给子过程我才用了%*,至于其他的分解参数是子过程自己的事。。。

所以你看我有个当第一个参数为/plp的时候,对参数2作为标签。。。。否则默认把第一个参数作为标签。。。

为了最大程度传递参数情况下保持代码简洁又可读性好些。。。
发表于 2011-5-23 22:23:13 | 显示全部楼层
11# qzwqzw


这个思路后再做些工作——就是统一接口。。。。
发表于 2011-5-24 08:51:58 | 显示全部楼层
12# plp626
call存在对"^"的错误处理
而且使用 call :label 会丢失掉%0
而在 :label 中可能会使用到这个 %0
比如遇到错误时的抛出处理
或者对自身文本内容的操作
所以在此之前需要 set program_name=%0

至于%1 %2 %3
即使goto到:label
也仍然可以使用%*分析命令行
而call:%2 %*会把/plp也传进去
这未必是你想看到的吧?

“如果shift要goto费时”
没看懂

下面是采用:标志子过程调用的处理方法
调用采用 call lib.cmd :sub1 arg1 arg2

  1. @echo off
  2. for /f "tokens=2 delims=:" %%s in ("_%1") do shift/1&goto %%s

  3. :sub1
  4. echo %0-%1-%2-%3.
  5. echo %*.
  6. pause
  7. goto :eof
复制代码
下面是采用.标志子过程调用的处理方法
调用采用 call lib.cmd sub1. arg1 arg2

  1. @echo off
  2. if [%~sn1.]==[%~s1] shift/1&goto :%~sn1

  3. :sub1
  4. echo %0-%1-%2-%3.
  5. echo %*.
  6. pause
  7. goto :eof
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 06:02 , Processed in 0.021109 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表