Board logo

标题: [其他] 批处理中start与call的用法的区别是什么? [打印本页]

作者: LJanswer    时间: 2010-12-13 21:01     标题: 批处理中start与call的用法的区别是什么?

start与call的用法的区别?
作者: hanyeguxing    时间: 2010-12-13 21:17

call的最大特点是可以调用本批内的标签,继承父批的环境变量,返回时带着子批的环境变量,start不能。
作者: LJanswer    时间: 2010-12-13 22:16

有点抽象,能否举个例子说明一下?我接受批处理的时间不长,还只是个菜鸟。
作者: hanyeguxing    时间: 2010-12-13 22:25

  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
复制代码

作者: wc726842270    时间: 2010-12-14 00:04

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

通过4楼的例子,还有5楼提供的参考,我对start与call的区别有了进一步的了解,谢了!
作者: applba    时间: 2011-5-23 18:43

请问一个批处理a.cmd可以直接调用另一个批处理b.cmd内部的标签:sub吗?
作者: CrLf    时间: 2011-5-23 18:56

7# applba


据我所知,直接调用的好像没有
作者: applba    时间: 2011-5-23 19:20

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

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

sub是子过程,123是参数
作者: plp626    时间: 2011-5-23 19:30

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

我的库函数就这么搞的。。。当然不一定必须这么搞,,只是个思路。。。
作者: qzwqzw    时间: 2011-5-23 22:06

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跳转标签也是可以的
作者: plp626    时间: 2011-5-23 22:13

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

11# qzwqzw


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

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

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

为了最大程度传递参数情况下保持代码简洁又可读性好些。。。
作者: plp626    时间: 2011-5-23 22:23

11# qzwqzw


这个思路后再做些工作——就是统一接口。。。。
作者: qzwqzw    时间: 2011-5-24 08:51

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
复制代码





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