BATCH - 无法从函数的变量中返回正确的值

Posted

技术标签:

【中文标题】BATCH - 无法从函数的变量中返回正确的值【英文标题】:BATCH - can't return proper value in a variable from a function 【发布时间】:2020-01-10 13:11:42 【问题描述】:

我已经阅读了很多关于使用变量从批处理函数返回值的示例和问题,但我无法强制 Windows 7 x64 cmd.exe 为我执行此操作。 ;-)

我已经尝试了很多代码示例,但都没有达到我的预期。我编写了一个简短的批处理程序来了解如何做到这一点,但它也没有像我预期的那样工作。我找不到我做错了什么。

@echo off
SetLocal EnableDelayedExpansion
set x=10
echo x(1) = !x!
call :TestFunc !x!
echo x(2) = !x!
EndLocal
exit /b

:TestFunc
SetLocal EnableDelayedExpansion
set a=%~1
echo a(1) = !a!
set /a a=a+101
echo a(2) = !a!
set %~1=!a!
echo   %%~1 = %~1
echo ^^!%%~1^^! = !%~1!
EndLocal
exit /b

我预计set %1=!a! 将设置由:TestFunc 返回的唯一变量。但结果是:

>test_variables.bat
x(1) = 10
a(1) = 10
a(2) = 111
  %~1 = 10
!%~1! = 111
x(2) = 10

对我来说最令人惊讶的是%~1 的主体内部有两个变量:TestFunc - 一个是在本地设置的,另一个是传递给函数,也可能由函数返回,但没有改变在函数体内。

编辑

最后,感谢@Stephan,我的例子很有效:

@echo off
rem echo on
SetLocal EnableDelayedExpansion
set "x=10"
set "y=x"
echo x(1) = !x!
echo y(1) = !y!
call :TestFunc !y! !x!
echo ---------------------------------
echo x(2) = !x!
echo y(2) = !y!
EndLocal
exit /b

:TestFunc
SetLocal EnableDelayedExpansion
set a=%~2
echo a(1) = !a!
set /a a=!a!+101
echo a(2) = !a!
EndLocal & set "%~1=%a%"
exit /b

结果:

>test_variables.bat
x(1) = 10
y(1) = x
a(1) = 10
a(2) = 111
---------------------------------
x(2) = 111
y(2) = x

有两个技巧可以做:

    将第一个变量名 (x) 放入另一个变量 (y) 值中,并以两个变量名作为参数调用函数 @Stephan 在 EndLocal 子句 (EndLocal & set "%~1=%a%") 之后设置返回变量值的技巧。

【问题讨论】:

由于使用 setlocal/endlocal nothing:TestFunc 返回 - 另一个方面由 Stephan 回答 我错过了setlocal/endlocalthing。答案改编。 (谢谢,@LotPings) 【参考方案1】:

set %~1=!a! 设置一个以%~1 的值命名的变量(在您的示例中为10)。所以命令被解析为:set 10=111

(你不应该使用以数字开头的变量名)

我认为你想做的是:

echo on
set "var=xxx"
call :sub var 10
echo %var%
goto :eof

:sub
setlocal
set /a tmpvar=%~2+55
endlocal & set "%~1=%tmpvar%"

我离开了echo on 以准确了解解析器如何“翻译”您的代码。

主要技巧是让变量在endlocal 中存活下来。这是通过使用endlocal & set "%~1=%tmpvar% 行欺骗解析器来实现的; %tmpvar% 实际上是在endlocal 生效之前评估

【讨论】:

以数字开头的变量名不是一个好主意。两者都不使用tmptempdatetimerandomusernameerrorlevel 等,因为它们是系统定义的。在 startlocal/endlocal 括号内是安全的,但通常不是。它们是非常诱人的名字,但如果你使用它们,你可能会遇到意想不到的问题。 感谢@Stephan 的解释和主要技巧。它对我的批处理工作帮助很大 - 不完全符合我的预期,而是返回 vales。 ;-) 它对我来说仍然看起来很奇怪,我仍然看不清一切。在我的示例中,直到我将第一个 变量名称 设置为辅助变量值,它才起作用。 set "x=10" set "y=x" @Magoo,我没有命名任何以数字开头的变量,或者我没有故意这样做。 ;-) 我想做的是将变量(x)中的值(10)作为参数传递给函数,然后从传递给函数的变量中读取值,以某种方式更改它并将更改后的值返回给主函数程序。这就是它不起作用的原因 - 因为可能我的 value 被视为变量名。 @McVik :正如斯蒂芬解释的那样,设置%~1 实际上设置了一个名为10 的变量,因为%~1 的值是10。由于您使用的是delayedexpansion,因此批处理适当地报告!%~1! 是您分配给变量 10 (111)。事实上,批处理实际上没有其他语言将函数的 result 分配给某个变量的方式的“函数”。 Batch 只有 procedures 可以构造来模仿函数。还有很多松散的术语,人们使用熟悉的术语而不在每个帖子中附加战争与和平免责声明。 感谢@Magoo 的解释。现在对我来说很清楚了。 :-)

以上是关于BATCH - 无法从函数的变量中返回正确的值的主要内容,如果未能解决你的问题,请参考以下文章

无法从函数返回的变量索引到空数组,或访问返回的正则表达式数据时出现问题

通过 ctypes 从 Python 调用的 C 函数返回不正确的值

此函数为CameraPosition中的zoom参数返回null而不是正确的值,我无法弄明白

从 C++ 中的函数返回指针

这是我的循环的正确等价物吗?

返回引用