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

问题描述

我有两个.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>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...