问题
I have read a lot of examples and questions about returning values from batch functions using variables but I can't force Windows 7 x64 cmd.exe to do it for me. ;-)
I have already tried a lot of code examples but nothing has worked as I expected. I have written a short batch program to find out how to do it, but it also hasn't worked as I expected. I can't find what I'm doing wrong.
@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
I expected that set %1=!a!
will set the only variable being returned by the :TestFunc
. But the result is:
>test_variables.bat
x(1) = 10
a(1) = 10
a(2) = 111
%~1 = 10
!%~1! = 111
x(2) = 10
The most surprising for me was that there are two variables %~1
inside the body of the :TestFunc
- one is set locally and the other one, passed to the function and maybe also returned by the function, but not changed inside the function's body.
Edit
And finally, thanks to @Stephan, my exaple that is working:
@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
and the result:
>test_variables.bat
x(1) = 10
y(1) = x
a(1) = 10
a(2) = 111
---------------------------------
x(2) = 111
y(2) = x
There were two tricks to do:
- Put the first variable name (x) into the other variable (y) value and call the function with both variable names as parameters
- @Stephan's trick with setting returned variable value after the
EndLocal
clause (EndLocal & set "%~1=%a%"
).
回答1:
set %~1=!a!
sets a variable named by the value of %~1
(which is 10
in your example). so the command is parsed as: set 10=111
(you shouldn't use variablenames starting with a digit)
What I think you want to do is:
echo on
set "var=xxx"
call :sub var 10
echo %var%
goto :eof
:sub
setlocal
set /a tmpvar=%~2+55
endlocal & set "%~1=%tmpvar%"
I left echo on
to see exactly, how the parser "translates" your code.
The main trick is for the variable to survive an endlocal
. This is achieved by tricking the parser with the line endlocal & set "%~1=%tmpvar%
; %tmpvar%
is actually evaluated before endlocal
takes effect.
来源:https://stackoverflow.com/questions/57842646/batch-cant-return-proper-value-in-a-variable-from-a-function