如何解决如何从一个窗口批处理脚本调用另一个窗口批处理脚本,同时扩展两者的功能
我有两个.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 举报,一经查实,本站将立刻删除。