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

[原创] [批处理命令一日一教学 续](41)调用子过程或外部程序:call

[复制链接]
发表于 2011-11-28 21:48:50 | 显示全部楼层 |阅读模式
【原】[一日一教学]批处理系列帖子索引 http://bbs.bathome.net/thread-2576-1-1.html
【续】[一日一教学]批处理系列帖子索引 http://bbs.bathome.net/thread-13798-1-1.html


帮助信息:
  1. 从批处理程序调用另一个批处理程序。

  2. CALL [drive:][path]filename [batch-parameters]

  3.   batch-parameters   指定批处理程序所需的命令行信息。

  4. 如果命令扩展被启用,CALL 会如下改变:

  5. CALL 命令现在将卷标当作 CALL 的目标接受。语法是:

  6.     CALL:label arguments

  7. 一个新的批文件上下文由指定的参数所创建,控制在卷标被指定
  8. 后传递到语句。您必须通过达到批脚本文件末两次来 "exit" 两次。
  9. 第一次读到文件末时,控制会回到 CALL 语句的紧后面。第二次
  10. 会退出批脚本。键入 GOTO /?,参看 GOTO :EOF 扩展的描述,
  11. 此描述允许您从一个批脚本返回。

  12. 另外,批脚本文本参数参照(%0、%1、等等)已如下改变:


  13.      批脚本里的 %* 指出所有的参数(如 %1 %2 %3 %4 %5 ...)

  14.      批参数(%n)的替代已被增强。您可以使用以下语法:

  15.          %~1         - 删除引号("),扩展 %1
  16.          %~f1        - 将 %1 扩展到一个完全合格的路径名
  17.          %~d1        - 仅将 %1 扩展到一个驱动器号
  18.          %~p1        - 仅将 %1 扩展到一个路径
  19.          %~n1        - 仅将 %1 扩展到一个文件名
  20.          %~x1        - 仅将 %1 扩展到一个文件扩展名
  21.          %~s1        - 扩展的路径只含有短名
  22.          %~a1        - 将 %1 扩展到文件属性
  23.          %~t1        - 将 %1 扩展到文件的日期/时间
  24.          %~z1        - 将 %1 扩展到文件的大小
  25.          %~$PATH:1   - 查找列在 PATH 环境变量的目录,并将 %1
  26.                        扩展到找到的第一个完全合格的名称。如果
  27.                        环境变量名未被定义,或者没有找到文件,
  28.                        此修改符会扩展到空字符串

  29.     可以组合修改符来取得多重结果:

  30.         %~dp1       - 只将 %1 扩展到驱动器号和路径
  31.         %~nx1       - 只将 %1 扩展到文件名和扩展名
  32.         %~dp$PATH:1 - 在列在 PATH 环境变量中的目录里查找 %1,
  33.                       并扩展到找到的第一个文件的驱动器号和路径。
  34.         %~ftza1     - 将 %1 扩展到类似 DIR 的输出行。

  35.     在上面的例子中,%1 和 PATH 可以被其他有效数值替换。
  36.     %~ 语法被一个有效参数号码终止。%~ 修定符不能跟 %*
  37.     使用
复制代码
.


命令概括:
call,意为: 电话;呼叫;要求;访问。引申为“调用”。
batch-parameter,意为“批处理参数”。
label,意为“标签”。
argument,意为“参数”。

call表明,批处理其实也是有函数的。

参数详解:
1、从批处理程序调用另一个批处理程序(外部函数)?

新建两个批处理程序,分别命名为test.bat、hello.bat。
test.bat

  1. echo %1 %2
  2. pause
复制代码
.


hello.bat
  1. @echo off
  2. call test.bat hello world
  3. pause
复制代码
运行hello.bat,调用test.bat,结果显示。
.

从结果中可以看出,hello.bat执行了4条语句,第一条关闭回显(@echo off),第二条输出hello world,第三条、第四条暂停并提示(pause)。
从这里可以看出,从批处理程序调用另一个批处理程序的执行流程:先执行原批处理中的代码,当遇到调用时再执行完被调用的批处理中的所有代码,最后返回到原批处理再执行call语句之后的代码。这种执行流程,同样适用于call 调用标签(内部函数)


2.第一节test.bat中%1,%2是什么意思?

要明白test.bat中%1、%2是什么意思,我们得结合hello.bat中“call test.bat hello world”和test.bat中“echo %1 %2”来看。

hello.bat中的类容不变,试着修改test.bat中的内容。
test.bat
  1. echo  %2
  2. pause
复制代码
.

再次执行hello.bat,结果:
  1. world
  2. 请按任意键继续. . .
复制代码
.

“hello”不见了,只显示了“world”,这给人一种感觉,好像%1代表了“hello”,%2代表了“world”——事实上也确实如此。

我们可以将%1~%9这九个参数看成是批处理的形参,在这个例子中,%1,%2就是形参,而“hello”、 “world”就是实参。

这种参数的传递,执行流程就是在原批处理中将实参传递到被调用批处理中的形参中。



例如:
将hello.bat,test.bat进行如下修改。

hello.bat
  1. @echo off
  2. call test.bat 3 9
  3. pause
复制代码
.

test.bat
  1. Set /a n=%1+%2
  2. echo %n%
  3. pause
复制代码
.

运行hello.bat,结果返回12。

实参中的分隔符可以是空格、逗号、分号、等于号,“call test.bat 3 9”写成“call test.bat 3,9”、“call test.bat 3;9”、“call test.bat 3=9”都是可以的。


3.调用一个内部函数(标签)

如果把“被调用批处理”看成是外部函数,那么标签就可以看成是内部函数。

修改hello.bat的内容:
  1. @echo off
  2. call :1 "hello"
  3. pause
  4. exit
  5. :1
  6. echo.%~1
复制代码
.

call调用标签时冒号(:)不可以省略,和goto不同(goto跳转时,冒号可有可无)。




4.函数调用中非实参形参对应关系的变量值的相互传递。

hello.bat
  1. @echo off
  2. Set n=1
  3. call :1 "hello"
  4. pause
  5. exit
  6. :1
  7. echo.%~1
  8. echo %n%
复制代码
代码的执行结果:
  1. hello
  2. 1
  3. 请按任意键继续. . .
复制代码
.

以上结果说明,内部函数中,变量n的值,可以在主函数中定义,在被调用函数中输出。——这种结果,同样会出现在外部函数中(一个批处理调用另一个批处理)。


再次修改hello.bat
  1. @echo off
  2. call :1 "hello"
  3. echo %n%
  4. pause
  5. exit
  6. :1
  7. echo.%~1
  8. Set n=1
复制代码
.

结果:
  1. hello
  2. 1
  3. 请按任意键继续. . .
复制代码
以上结果说明,内部函数中,变量n的值,也可以在被调用函数中定义,在主函数中输出。——这种结果,同样会出现在外部函数中(一个批处理调用另一个批处理)。




5.嵌套调用

嵌套调用就是一个被调用的函数中还有一个调用其它函数的命令,就好像小时候玩的那工兵、班长、排长、连长、团长……,团长 call 连长,连长 call 排长,……,班长 call 工兵,然后工兵才开始干活。

修改两个批处理的内容:

hello.bat
  1. @echo off
  2. call test.bat world
  3. echo %m%
  4. pause&exit
复制代码
.

test.bat
  1. Echo %1
  2. Set m=1
  3. call :1 hello
  4. pause&exit /b
  5. :1
  6. echo %1
复制代码
.

结果:
  1. world
  2. hello
  3. 请按任意键继续. . .
  4. 1
  5. 请按任意键继续. . .
复制代码
.

这里,test.bat是被调用的函数,但它自身又包含一个内部子函数(:1)——这就是函数的嵌套。

可以看出虽然test.bat中有两个%1,但是它们的值并不相同,这说明父函数的形参并不等于子函数的形参。


注意:这里exit /b 是用来退出子函数的,不加/b参数就会退出整个cmd.exe(区别就是,加/b父函call之后命令还会执行,不加/b父函数call之后的命令就不会执行了)。
可以把test.bat中的exit /b 替换为 exit 体会一下。

6.函数的递归调用

http://bbs.bathome.net/thread-1264-1-6.html
这篇教程由pusofalse提供。


扩展阅读:

1.利用call实现变量延迟。
  1. @echo off
  2. for /l %%i in (1 1 5) do (
  3.         Set n=%%i
  4.         set /a n+=1
  5.         call echo %%n%%
  6. )
  7. pause
复制代码
.

2.call和for一起使用。
  1. ::在文件路径前加“this is a text”
  2. @echo off
  3. For /r %%i in (*.txt) do call :1 %%i
  4. pause
  5. :1
  6. Set n=This is a text:%1
  7. echo %n%
复制代码
.

第二种方法的作用其实更大。但是第一种方法用的却更多。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评分

参与人数 1技术 +1 收起 理由
Batcher + 1 Good work!

查看全部评分

发表于 2012-2-10 13:26:41 | 显示全部楼层
  1. call echo %%n%%
复制代码
这个不错
发表于 2012-2-12 23:12:20 | 显示全部楼层
回复 1# Hello123World


    总算明白%1~9的用法了
发表于 2012-5-8 19:51:02 | 显示全部楼层
对批处理越来越佩服了
发表于 2013-9-15 17:49:34 | 显示全部楼层
学到很多,每天都进步一点,谢谢分享。
发表于 2014-4-2 20:27:52 | 显示全部楼层
深有体会啊!遇到变量引用时非常有用1# Hello123World
发表于 2014-4-5 18:21:36 | 显示全部楼层
最后一例显示为:
This is a text:%1     ???
发表于 2015-1-2 15:53:18 | 显示全部楼层
批处理博大精深,学习了
发表于 2015-1-21 17:18:18 | 显示全部楼层
@echo off
rem 用^call命令去理解%*这些常理的应用
call :x 1 10
pause&exit
:x
for /l %%i in (%1,%1,%2) do echo %%i
发表于 2017-8-19 10:50:33 | 显示全部楼层
call echo %%n%%还一定要加两层%%
发表于 2017-9-26 21:50:14 | 显示全部楼层
为什么是要加两层%呢,是什么意思呢?
发表于 2017-9-27 11:53:54 | 显示全部楼层
有一些行确实看不明白,希望指教一下
call echo %%n%% 这句是什么意思呢?
call echo 怎么理解?
%%n%% 又怎么理解?

谢谢
发表于 2018-8-29 22:48:52 | 显示全部楼层
嵌套调用,有些地方又叫函数链式调用

批处理中的变量定义范围好像没的javascript那么受限制一样,全局或局部
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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