批量 - 通过延迟扩展获取本地值
Batch - Get value of local with delayed expansion
在下面的代码中,我创建了一些伪数组(表示对)并调用了一个例程,该例程获取伪数组的名称及其大小作为参数值。在例程中,我想循环访问每个数组元素。据我所知,访问数组值的唯一可能性是使用延迟扩展,如果我可以在本地取回延迟扩展的值,这将不是问题。
@ECHO OFF
SETLOCAL DISABLEDELAYEDEXPANSION
set pairs[0]="a" "b"
set pairs[1]="c" "d"
set pairs[2]="e" "f"
set pairNumber=3
call :my_routine pairs %pairNumber%
ENDLOCAL
EXIT /B 0
:my_routine
SETLOCAL DISABLEDELAYEDEXPANSION
set myPairs=%1
set /a maxCount=%2-1
for /l %%c in (0,1,%maxCount%) do (
set "currentPair="
SETLOCAL ENABLEDELAYEDEXPANSION
call set "pair=%%!myPairs![%%c]%%"
REM setting the value works:
REM echo !pair!
ENDLOCAL & set "currentPair=%pair%"
echo %currentPair%
)
ENDLOCAL
exit /b 0
预期输出:
"a" "b"
"c" "d"
"e" "f"
关键的部分是& set currentPair=%pair%
。据我了解,未设置 %pair%
值是因为在设置时使用了延迟扩展。
问题是关于取回价值,而不是告诉我我可以在当地做事。如果没有办法取回价值,我会考虑这一点。
我也看过 this 非常相似的问题,但解决方案对我不起作用。
所以...
如何从内部本地中获取值,以便 currentPair
获取 pair
的值?
我敢肯定这不是你想要的;但根据您提供的有限信息和已知的字符串内容,无需在 For /L
循环中设置不必要的变量或启用和禁用延迟扩展。
@Echo Off
SetLocal DisableDelayedExpansion
Set "pairs[0]="a" "b""
Set "pairs[1]="c" "d""
Set "pairs[2]="e" "f""
Set "pairNumber=2"
Call :my_routine pairs %pairNumber% currentPair
Exit /B 0
:my_routine
SetLocal EnableDelayedExpansion
For /L %%A In (0,1,%2) Do Set "%3=!%1[%%A]!" & Echo !%3!
Pause
Exit /B 0
如果需要,您可以选择将 Echo !%3!
更改为 Set %3
每个 SetLocal
将 EndLocal
及其各自的 Exit
将变量值传递到 endlocal
屏障之外的通常方法依赖于这样一个事实,即它没有放在代码块中,而是将行 endlocal & set "currentPair=%pair%"
放在 for /L
循环。
您可以改用 for /F
循环,如下所示:
for /F "delims=" %%E in (""!pair!"") do (
endlocal
set "currentPair=%%~E"
)
!pair!
周围的一对引号告诉 for /F
它是一个文字字符串;内部对是该字符串的一部分,然后由 %%~E
中的 ~
修饰符删除。这样做的目的是确保循环始终迭代一次(即使 !pair!
为空),因此 endlocal
被执行。
这也适用于另一个代码块,例如您的 for /L
循环。
当然 echo %currentPair%
行不是 return 正确的字符串,但您可以将 echo(%%~E
放在 for /F
循环中。
在下面的代码中,我创建了一些伪数组(表示对)并调用了一个例程,该例程获取伪数组的名称及其大小作为参数值。在例程中,我想循环访问每个数组元素。据我所知,访问数组值的唯一可能性是使用延迟扩展,如果我可以在本地取回延迟扩展的值,这将不是问题。
@ECHO OFF
SETLOCAL DISABLEDELAYEDEXPANSION
set pairs[0]="a" "b"
set pairs[1]="c" "d"
set pairs[2]="e" "f"
set pairNumber=3
call :my_routine pairs %pairNumber%
ENDLOCAL
EXIT /B 0
:my_routine
SETLOCAL DISABLEDELAYEDEXPANSION
set myPairs=%1
set /a maxCount=%2-1
for /l %%c in (0,1,%maxCount%) do (
set "currentPair="
SETLOCAL ENABLEDELAYEDEXPANSION
call set "pair=%%!myPairs![%%c]%%"
REM setting the value works:
REM echo !pair!
ENDLOCAL & set "currentPair=%pair%"
echo %currentPair%
)
ENDLOCAL
exit /b 0
预期输出:
"a" "b"
"c" "d"
"e" "f"
关键的部分是& set currentPair=%pair%
。据我了解,未设置 %pair%
值是因为在设置时使用了延迟扩展。
问题是关于取回价值,而不是告诉我我可以在当地做事。如果没有办法取回价值,我会考虑这一点。
我也看过 this 非常相似的问题,但解决方案对我不起作用。
所以...
如何从内部本地中获取值,以便 currentPair
获取 pair
的值?
我敢肯定这不是你想要的;但根据您提供的有限信息和已知的字符串内容,无需在 For /L
循环中设置不必要的变量或启用和禁用延迟扩展。
@Echo Off
SetLocal DisableDelayedExpansion
Set "pairs[0]="a" "b""
Set "pairs[1]="c" "d""
Set "pairs[2]="e" "f""
Set "pairNumber=2"
Call :my_routine pairs %pairNumber% currentPair
Exit /B 0
:my_routine
SetLocal EnableDelayedExpansion
For /L %%A In (0,1,%2) Do Set "%3=!%1[%%A]!" & Echo !%3!
Pause
Exit /B 0
如果需要,您可以选择将 Echo !%3!
更改为 Set %3
每个 SetLocal
将 EndLocal
及其各自的 Exit
将变量值传递到 endlocal
屏障之外的通常方法依赖于这样一个事实,即它没有放在代码块中,而是将行 endlocal & set "currentPair=%pair%"
放在 for /L
循环。
您可以改用 for /F
循环,如下所示:
for /F "delims=" %%E in (""!pair!"") do (
endlocal
set "currentPair=%%~E"
)
!pair!
周围的一对引号告诉 for /F
它是一个文字字符串;内部对是该字符串的一部分,然后由 %%~E
中的 ~
修饰符删除。这样做的目的是确保循环始终迭代一次(即使 !pair!
为空),因此 endlocal
被执行。
这也适用于另一个代码块,例如您的 for /L
循环。
当然 echo %currentPair%
行不是 return 正确的字符串,但您可以将 echo(%%~E
放在 for /F
循环中。