Windows批处理SETLOCAL enabledelayedexpansion调用的返回值 [英] Windows batch setlocal enabledelayedexpansion call return value

查看:235
本文介绍了Windows批处理SETLOCAL enabledelayedexpansion调用的返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有两(2)Windows批处理脚本。第一个将调用第二个。然而,SETLOCAL必须在随时待命,因为ENABLEDELAYEDEXPANSION需要在for循环中用于第二批脚本。

There are two (2) Windows batch scripts. The first one will CALL the second one. However, SETLOCAL must be used around the call to the second batch script because ENABLEDELAYEDEXPANSION is needed in a FOR loop.

=== batch1.bat

=== batch1.bat

@echo off
echo in %0
set BAT1_VAR=5
SETLOCAL
    call  batch2.bat
    set|find "BAT"
    echo === before endlocal
ENDLOCAL
set|find "BAT"
echo === after endlocal
echo === begin exiting %0
set|find "BAT"
echo === end exiting %0
exit /B 0

=== batch2.bat

=== batch2.bat

@echo off
echo in %0
SET BAT2_VAR=7
echo === begin exiting %0
SET|FIND "BAT"
echo === end exiting %0
EXIT /B 0

===
的问题是,由batch2.bat设置变量需要返回batch1.bat后仍然存在。这可以通过使用来解决:

=== The problem is that the variable set by batch2.bat needs to still exist after the return to batch1.bat. This can be resolved by using:

ENDLOCAL & set BAT2_VAR=%BAT2_VAR%

不过,我不希望batch1.bat需要知道的由batch2.bat创建的变量的名称。可能有很多和列表可能更改。

HOWEVER, I do not want batch1.bat to need to know the names of variables created by batch2.bat. There might be many and the list may change.

任何想法解决这个问题?谢谢你。

Any ideas to overcome this problem? Thanks.

推荐答案

如果你是在一个循环中,或code中的任何括号的块,那么你就不能使用 ENDLOCAL&安培;设置BAT2_VAR =%BAT2_VAR%方法。

If you are in a loop, or any parenthesized block of code, then you cannot use the ENDLOCAL & set BAT2_VAR=%BAT2_VAR% method.

这样的事情会失败

REM delayed expansion is disabled to start
for ... %%A in (....) do (
   REM must SET before enabling delayed expansion to preserve ! in %%A value
   set var=%%A
   REM the remainder of the loop needs delayed expansion
   setlocal enableDelayedExpansion
   REM do something with !var!
   call batch2 !var!
   REM maybe the batch2 modifies var some more
   REM Must endlocal and preserve the value. The attempt below fails because %var% will
   REM be the value that existed before the loop was entered
   endlocal & set "var=%var%"
)

有一个简单的解决方法是通过FOR变量传输的值

A simple fix is to transfer the value via a FOR variable

REM delayed expansion is disabled to start
for ... %%A in (....) do (
   REM must SET before enabling delayed expansion to preserve ! in %%A value
   set var=%%A
   REM the remainder of the loop needs delayed expansion
   setlocal enableDelayedExpansion
   REM do something with !var!
   call batch2 !var!
   REM maybe the batch2 modifies var some more
   REM the code below successfully transports the value across the endlocal barrier
   for /f "delims=" %%B in ("!var!") do endlocal & set "var=%%B"
)

您说您的批处理可以设置你需要preserve多个值。通常情况下你传递返回变量的名称到您的调用程序,然后你的日常可以做这样的事情:

You say your batch might set many values you need to preserve. Normally you pass the names of the return variables into your CALLed routine, and then your routine could do something like:

set "%~2=return value1"
set "%~3=return value2"
... etc.

您会知道所有变量的名称,但可能需要大量的code的运输所有值翻过的ENDLOCAL障碍。

You would know the names of all the variables, but that might require a lot of code to transport all values accross the endlocal barrier.

您可以preFIX都具有共同的preFIX变量,然后用FOR / F循环preserve值。任何迭代开始前,整个结果集的FOR / F(命令)将被缓存。

You could prefix all the variables with a common prefix, and then use a FOR /F loop to preserve the values. The entire result set of a FOR /F ('command') is cached before any of the iterations begin.

您称为批处理可以设置变量 prefix.var1 prefix.var2 。 .. prefix.varN ,下面code将工作

Your CALLed batch could set variables prefix.var1, prefix.var2, ... prefix.varN, and the following code would work

REM delayed expansion is disabled to start
for ... %%A in (....) do (
   REM must SET before enabling delayed expansion to preserve ! in %%A value
   set var=%%A
   REM the remainder of the loop needs delayed expansion
   setlocal enableDelayedExpansion
   REM do something with !var!
   call batch2 !var! prefix.
   REM the batch2 set variables prefixed by prefix.
   REM Must endlocal and preserve all values.
   for /f "delims=" %%B in ('set prefix.') do (
     if "!"=="" endlocal
     set "%%B"
   )
)

如果!==ENDLOCAL 行是一个极好的把戏,只ENDLOCAL一号内部循环迭代。它依赖于延迟扩展被外环之前禁用,并且邻近每个外循环迭代的顶部启用事实

The if "!"=="" endlocal line is a nifty trick to only endlocal on the 1st inner loop iteration. It relies on the fact that delayed expansion was disabled before the outer loop, and enabled near the top of each outer loop iteration.

这篇关于Windows批处理SETLOCAL enabledelayedexpansion调用的返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆