SETLOCAL
...ENDLOCAL
彻底地注入局部变量,以至于尝试计算值并返回值的函数会失败。
通常,这些函数使用for
-解析文件和字符串do
,并依赖于SETLOCAL enabledelayedexpansion
计算值。
多年来,我通过将值传递给临时文件并恢复它来解决了这个问题,如下例所示。
然而……这是 非常 速度很慢,尤其是涉及递归时,因为需要不断进行读/写/创建循环。
甚至由创建的系统范围变量也会SETX
失败,因为SETLOCAL
会创建并发布本地版本。它是万无一失的~或者看起来是。
多年来,我一直在研究这个问题,这个问题让我一直很头疼。也许有人已经解决了它?以下是示例代码:
示例代码
@echo off
set _str=
call :RandomFunction %*
:: back from the function
echo:
echo: now try to recover the variables
set _ & echo: _ReturnStr not there
echo:
echo: so collect it from the temp file
for /f "delims=" %%V in ('more^<_passvalue.txt') do set _str=%%V
echo: [%_str%] is returned
echo: *sigh* there must be a better way!
exit /b
该函数名为:
:RandomFunction
@echo off
set _anotherstr=asdfg
setlocal & rem most times enabledelayedexpansion
set _localReturnValue=
echo: this function is invoked and [%*] set of parameters comes in
:: and stuff happens
:: at the end of it all a value is ready to be returned!
set "_localReturnValue=ImBreakingOut" & rem this is it
:: at the same time send it to a file
echo:%_localReturnValue%>_passValue.txt
endlocal
SET "_ReturnStr=%_localReturnValue%" & rem trying to recover it to be returned
echo: trying to echo the _ReturnStr= [%_ReturnStr%] after ENDLOCAL
echo: Post ENDLOCAL it was released
echo: but _anotherstr= [%_anotherstr%] does persist
exit /b
:: /RandomFunction
控制台的输出是
>f 123 abc
this function is invoked and [123 abc] set of parameters comes in
trying to echo the _ReturnStr= [] after ENDLOCAL
Post ENDLOCAL it was released
but _anotherstr= [asdfg] does persist
now try to recover the variables
_anotherstr=asdfg
_ReturnStr not there
so collect it from the temp file
[ImBreakingOut] is returned
*sigh* there must be a better way!
>
答案1
答案是隧道
哦天哪。我是个白痴。
弗兰克·西纳特拉有答案。乔治·克鲁尼也有。
这叫做“隧道”啊啊啊。
天啊,我们怎么这么容易忘记。
西蒙·谢泼德在他的 SS64 网站上很好地阐述了这一点如何创建和使用批处理文件函数页:
解决这个问题的方法是利用 CMD shell 逐行评估变量的事实 - 因此将 ENDLOCAL在同一条线上因为 SET 语句给出了我们想要的结果。这种技术称为“隧道”,适用于函数和整个批处理脚本
重写代码
@echo off
call :RandomFunction %*
:: back from the function
echo:
echo: now recover the variable created in the function
echo: the value of variable _ReturnStr = [%_ReturnStr%]
echo:
echo: so no need to collect from a temp file
echo: *sigh* there has always beeen a better way!
exit /b
:RandomFunction
@echo off
setlocal & rem most times enabledelayedexpansion
set _localReturnValue=
echo: this function is invoked and [%*] set of parameters comes in
:: and stuff happens
:: at the end of it all a value is ready to be returned!
set "_localReturnValue=ImBreakingOut" & rem this is it
:: concurrently execute the variable assignment wit the ENDLOCAL command
endlocal & SET "_ReturnStr=%_localReturnValue%"
exit /b
:: /RandomFunction
现在给出了正确答案
>_temp abc 123
this function is invoked and [abc 123] set of parameters comes in
now recover the variable created in the function
the value of variable _ReturnStr = [ImBreakingOut]
so no need to collect from a temp file
*sigh* there has always beeen a better way!
>