微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从一个窗口批处理脚本调用另一个窗口批处理脚本,同时扩展两者的功能

如何解决如何从一个窗口批处理脚本调用另一个窗口批处理脚本,同时扩展两者的功能

我有两个.bat文件,都使用延迟扩展,因此我可以在for循环中设置变量。

下面的示例已大大简化,仅用于显示问题

脚本one.bat

@echo off

setlocal enableextensions
setlocal enabledelayedexpansion

set j=0
for /L %%i in (1,1,2) do (
  set j=%%i
  set /A j=!j! + 1
  echo %%i !j!
  two.bat
  echo %%i !j!
)

脚本two.bat

@echo off

setlocal enableextensions
setlocal enabledelayedexpansion

echo Hello World

exit /B 0

two.bat返回的变量!j!丢失,并且echo重新打开。

J:\>one
1 2
Hello World
1 !j!

J:\>(
set j=2
 set /A j=!j! + 1
 echo 2 !j!
 two.bat
 echo 2 !j!
)
Missing operator.
2 !j!
Hello World
2 !j!

是的,我可以在two.bat中使one.bat成为子例程,但是它有一百行,而且我不想维护两个相同逻辑的副本

在这里想念什么?

解决方法

您的假设错误是执行从文件two.bat返回,因为只有在使用call command 1 的情况下。

批处理文件one.bat在括号内的代码块中运行two.bat,该代码块已在命令堆栈 2 中,因此该块(有点)已完成终止执行。


您的输出完美地说明了会发生什么(因此我在这里进行了评论):

J:\>one              
1 2                  /* first loop iteration,the first `echo %%i !j!` in the block is
                        executed as expected; */
Hello World          /* `two.bat` is run; execution does NOT return to `one.bat`,because there is NO `call`,which would put a return point onto
                        the stack! the only thing remembered and thus accomplished is
                        the current command line or parenthesised block; */
1 !j!                /* the second `echo %%i !j!` in the block is executed as it is
                        still buffered,but `two.bat` is already quit,hence implicit
                        `endlocal` commands have been executed,so all the nested
                        `setlocal` commands in your scripts are cancelled and delayed
                        expansion is disabled (default state); moreover,variable `j` is
                        no longer defined here; */
                     /* at this point,the parenthesised block,which is the loop body,has been executed,hence batch file context is left and Command
                        Prompt context applies,so `@echo off` from `one.bat` does no
                        longer apply here; */
J:\>(                // this block is nothing but the echo of the second loop iteration,set j=2              // which is still buffered;
 set /A j=!j! + 1    
 echo 2 !j!          
 two.bat             
 echo 2 !j!          
)                    
Missing operator.    /* this error message is caused by the attempt to execute
                        `set /A j=!j! + 1` (remember that delayed expansion is no longer
                        enabled and `j` is undefined); */
2 !j!                // first `echo %%i !j!` in the buffered second loop iteration;
Hello World          /* `two.bat` is run again; afterwards,batch file context is left
                        again and Command Prompt context applies; */
2 !j!                // second `echo %%i !j!` in the buffered second loop iteration;

要证明执行是在批处理文件还是在命令提示符上下文下发生,只需将set /A j放置在one.bat中的循环主体中作为最后一条命令,这样您将获得一个附加输出0在输出1 !j!和第二个2 !j!之后,因为set /A在批处理文件上下文中不返回任何内容,但是在Command中输出了(最后)结果(没有尾随换行符)及时的环境; 0的值表明不再设置j


1)有一些例外:被调用的批处理文件包含在管道中,或者由for /F loop运行和解析,因为批处理文件在新的{{3}中运行}在这种情况下。
2)如果被调用的批处理文件包含在带有串联命令的行中,则同样如此,因此,two.bat & echo Fine之类的东西在执行Fine时会回显two.bat sub>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。