gpt4 book ai didi

batch-file - 从批处理文件中的可变参数函数返回变量列表

转载 作者:行者123 更新时间:2023-12-03 16:35:54 26 4
gpt4 key购买 nike

我有一个函数,它接受可变数量的参数。每个参数都是函数将直接修改的引用。以下是我调用该函数的方式:

set "A=" && set "B=" && set "C="
call :variadic_func A B C
echo [%A%][%B%][%C%]

goto :eof

如果我不使用 setlocal 来限制变量范围,该函数可以正常工作。该函数创建引用 X、Y 和 Z,并为它们赋值 1、2 和 3。当函数返回时,调用者看到其变量 A、B 和 C 为 1、2 和 3。很好。假设这是一个可变参数函数,它计算出它在运行时有多少个参数。

:variadic_func
set "x=%1" && set "y=%2" && set "z=%3"
set "%x%=1" && set "%y%=2" && set "%z%=3"
goto :eof

输出:

C:\scratch\variadic_batch>variadic.bat
[1][2][3]

但是我想用 setlocal 来限制我的函数变量的范围。所以这意味着我写入 X、Y 和 Z 的任何值都会在 endlocal 处被丢弃。如何从函数中获取值?

:variadic_func
setlocal
set "x=%1" && set "y=%2" && set "z=%3"
set "%x%=1" && set "%y%=2" && set "%z%=3"

endlocal && (
call set "%x%=%%%%x%%%%"
call set "%y%=%%%%y%%%%"
call set "%z%=%%%%z%%%%"
)

goto :eof

不幸的是,调用上下文接收到值 %x%%y%%z%。我以为上面的代码会这样展开: 1. 先展开%x%得到call set A=%%A%%。然后执行调用并计算 A=%A%。但我最终只是将文本 %A% 分配给变量 A 而不是对其求值。

C:\scratch\variadic_batch>variadic.bat
[%x%][%y%][%z%]

为什么它没有像我预期的那样工作,我该如何解决?

(我只是想在函数调用之前执行 setlocal EnableDelayedExpansion,所以当我在函数中执行 endlocal 时,延迟扩展可能仍然可用,但即使这样做也很好如果函数不依赖于调用者处于延迟扩展 block 中......我什至不知道延迟扩展 block 是否堆栈)

最佳答案

这是一个有趣的话题!如果您事先知道该函数将获得多少变量,您可以在末尾组装适当的行,以这种方式将值返回给调用者的环境:

:variadic_func
setlocal EnableDelayedExpansion
set "x=%1" & set "y=%2" & set "z=%3"
set "%x%=1" & set "%y%=2" & set "%z%=3"
for /F "tokens=1-3" %%a in ("!%x%! !%y%! !%z%!") do (
endlocal
set "%x%=%%a" & set "%y%=%%b" & set "%z%=%%c"
)
exit /B

但是,如果变量个数未知,前面的方法就不能用了。

(我使用 exit/B 来终止子程序和 goto :EOF 仅用于主文件)

你的例子无论如何都不精确,因为如果你不知道有多少个变量,你就不能使用固定名称如“x”、“y”或“z”。处理这种情况的唯一方法是将名称存储在数组 中,然后处理数组元素。

这样,在函数结束之前,我们可以组装一个“var=value”对列表,它们将在 endlocal 之后在 FOR 中执行,因此变量将在调用者的环境中定义:

@echo off

call :variadic_func One Two Three
echo THREE VARS: One=[%One%] Two=[%Two%] Three=[%Three%] Four=[%Four%] Five=[%Five%]
call :variadic_func One Two Three Four Five
echo FIVE VARS: One=[%One%] Two=[%Two%] Three=[%Three%] Four=[%Four%] Five=[%Five%]
goto :EOF

:variadic_func
setlocal EnableDelayedExpansion
rem Collect the list of variable names in "var" array:
set i=0
:nextVar
if "%1" equ "" goto endVars
set /A i+=1
set var[%i%]=%1
shift
goto nextVar
:endVars
rem Assign random numbers to the variables (for example):
for /L %%i in (1,1,%i%) do (
set !var[%%i]!=!random!
)
rem Assemble the list of "var=value" assignments that will be executed at end:
set assignments=
for /L %%i in (1,1,%i%) do (
for %%v in (!var[%%i]!) do (
set assignments=!assignments! "%%v=!%%v!"
)
)
rem Execute the list of variable assignments in the caller's environment:
endlocal & for %%a in (%assignments%) do set %%a
exit /B

输出:

THREE VARS: One=[29407] Two=[21271] Three=[5873] Four=[] Five=[]
FIVE VARS: One=[30415] Two=[2595] Three=[22479] Four=[13956] Five=[26412]

编辑:

我从 dbenham 的解决方案中借用了方法来返回任意数量的变量,没有限制,除了他指出的变量。这是新版本:

@echo off

call :variadic_func One Two Three
echo THREE VARS: One=[%One%] Two=[%Two%] Three=[%Three%] Four=[%Four%] Five=[%Five%]
call :variadic_func One Two Three Four Five
echo FIVE VARS: One=[%One%] Two=[%Two%] Three=[%Three%] Four=[%Four%] Five=[%Five%]
goto :EOF

:variadic_func
setlocal EnableDelayedExpansion
rem Assemble the list of variable names in "var" array:
set i=0
:nextVar
if "%1" equ "" goto endVars
set /A i+=1
set var[%i%]=%1
shift
goto nextVar
:endVars
rem Assign random numbers to the variables (for example):
for /L %%i in (1,1,%i%) do (
set !var[%%i]!=!random!
)
rem Complete "var[i]=name" array contents to "var[i]=name=value"
for /L %%i in (1,1,%i%) do (
for %%v in (!var[%%i]!) do (
set "var[%%i]=%%v=!%%v!"
)
)
rem Execute the list of variable assignments in the caller's environment:
for /F "tokens=1* delims==" %%a in ('set var[') do endlocal & set "%%b"
exit /B

安东尼奥

关于batch-file - 从批处理文件中的可变参数函数返回变量列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14221369/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com