[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

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

start与call的用法的区别?

call的最大特点是可以调用本批内的标签,继承父批的环境变量,返回时带着子批的环境变量,start不能。
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

有点抽象,能否举个例子说明一下?我接受批处理的时间不长,还只是个菜鸟。

TOP

  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
复制代码
寒夜孤星:在没有说明的情况下,本人所有代码均运行在 XP SP3 下 (有问题请发贴,QQ临时会话已关闭)

TOP

说实话个人认为LZ还是先了解一下START。CALL这两个命令的基础比较好,至于区别即使给你答案,也会事半功倍
如果想暂时的了解一下参考下http://www.bathome.net/viewthrea ... amp;highlight=start
另外论谈的搜索功能也是非常的强大,有什么不明白的地方,这应该是首选

TOP

通过4楼的例子,还有5楼提供的参考,我对start与call的区别有了进一步的了解,谢了!

TOP

请问一个批处理a.cmd可以直接调用另一个批处理b.cmd内部的标签:sub吗?

TOP

7# applba


据我所知,直接调用的好像没有

TOP

比如我把很多常用的子过程或者函数放到一个批处理里面。

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

sub是子过程,123是参数

TOP

比如说子过程库(标签以/开头)文件为sos.cmd
添加“文件头”:
  1. @(
  2.   if "%~1"=="/plp" (
  3. call:%2 %*
  4.   )else call:%*
  5.   goto:eof
  6. )
复制代码
然后 sos/子过程标签 参数列表

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

评分人数

TOP

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跳转标签也是可以的
天的白色影子

TOP

本帖最后由 plp626 于 2011-5-23 22:18 编辑

11# qzwqzw


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

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

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

为了最大程度传递参数情况下保持代码简洁又可读性好些。。。

TOP

11# qzwqzw


这个思路后再做些工作——就是统一接口。。。。

TOP

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
复制代码
天的白色影子

TOP

返回列表