windows - 如何从另一个 Windows 批处理脚本调用一个 Windows 批处理脚本,并在两者中都启用延迟扩展

标签 windows batch-file variables scripting delayedvariableexpansion

我有两个 .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中,所以该 block 在终止执行之前已经(某种程度上)完成了。


您的输出完美地说明了发生的情况(因此我在这里评论了它):

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 的循环体中作为最后一个命令,这样在输出 1 !j! 和第二个 2 !j! 之后,您将获得额外的输出 0,因为 set/A 在批处理文件上下文中不返回任何内容,但它在命令提示符上下文中输出(最后)结果(没有尾随换行符); 0 的值表明 j 不再设置。


1) 有一些异常(exception):被调用的批处理文件涉及管道,或者由 for /F loop 运行和解析。 ,因为批处理文件在新的 cmd.exe 中运行此类情况的实例。
2) 如果被调用的批处理文件包含在具有串联命令的行中,情况也是如此,因此诸如 two.bat & echo Fine 之类的内容将回显 Fine执行 two.bat.

关于windows - 如何从另一个 Windows 批处理脚本调用一个 Windows 批处理脚本,并在两者中都启用延迟扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64022201/

相关文章:

windows - 无法创建/打开锁文件 :\data\db\mongod. 锁

asp.net - 您实现/使用 WebDAV 有哪些经验?

file - 将文件复制到多个文件夹,而不是子文件夹批量

windows - 单色图像显示为彩色RGB图像

java - 运行 Java 小程序时出现问题

batch-file - 我的 for/f 语句有什么问题

windows - 从批处理文件发送电子邮件的最佳方式是什么?

java - 如何将变量递增到字母表中的下一个或上一个字母?

php - 需要有关变量 COUNT 查询的帮助

javascript - JS-设置全局变量