使用shift在for循环中批量解析传入参数
Parsing incomming parameters in batch inside for loop with shift
我正在尝试编写 "bootstrapper" 脚本来解析参数并将其传递到我的框架中的其他应用程序中。下面是最小的、可重现的例子,实际应用要复杂得多
该脚本的基本语法是
bootstrapper.bat type command "foo=1" "bar=test2" "baz=true"
它应该调用
type/command.bat 1 test2 true
有问题的片段是这个嵌套的 for 循环:
setlocal enabledelayedexpansion
rem this is actually fetched elsewhere in live app
set procedure_arguments_count=3
set arguments=
for /L %%L in (1,1,!procedure_arguments_count!) do (
for /f "tokens=1,2 delims==" %%a in ("%~3") do set arguments=!arguments! %%b
shift /3
)
echo !arguments!
问题是 arguments
在执行此循环后等于 1 1 1
而不是 1 test2 true
。
我相信内部循环已预先填充 %~3
并设置为 foo=1
并忽略了 shift 命令。我无法更改 shift
,因为我需要支持 9 个以上的参数,也无法删除外部循环(出于其他原因)。
问题是 - 我可以延迟扩展脚本参数吗?
你的问题是,%x
参数甚至在 for
循环执行之前被解析器替换为它们的初始值,所以 shift
在 for
循环中没有(立即)效果。
一个简单的解决方法:将参数 3....n 分配给一个变量并处理:
setlocal enabledelayedexpansion
for /f "usebackq tokens=2,*" %%i in ('%*') do (
for %%k in (%%j) do (
for /f "tokens=2 delims==" %%a in ("%%~k") do (
set "args=!args! %%~a"
)
)
)
set args
第一个 for
得到参数 3...
第二个 for
处理您剩余的每个参数
第三个 for
从每个 var=value
字符串中获取值。
@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
rem this is actually fetched elsewhere in live app
set procedure_arguments_count=3
set arguments=
for /L %%L in (1,1,!procedure_arguments_count!) do (
call set "aux=%%~3"
for /f "tokens=1,2 delims==" %%a in ("!aux!") do set arguments=!arguments! %%b
shift /3
)
echo !arguments!
或没有外部 FOR /L
循环
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "procedure_arguments_count=3"
set "arguments="
set "ii=%procedure_arguments_count%"
:loopfor
if [%3]==[] goto :done
if %ii% EQU 0 goto :done
for /f "tokens=1,2 delims==" %%a in ("%~3") do set arguments=%arguments% %%b
SHIFT /3
set /A ii-=1
goto :loopfor
:done
echo(%arguments%
我正在尝试编写 "bootstrapper" 脚本来解析参数并将其传递到我的框架中的其他应用程序中。下面是最小的、可重现的例子,实际应用要复杂得多
该脚本的基本语法是
bootstrapper.bat type command "foo=1" "bar=test2" "baz=true"
它应该调用
type/command.bat 1 test2 true
有问题的片段是这个嵌套的 for 循环:
setlocal enabledelayedexpansion
rem this is actually fetched elsewhere in live app
set procedure_arguments_count=3
set arguments=
for /L %%L in (1,1,!procedure_arguments_count!) do (
for /f "tokens=1,2 delims==" %%a in ("%~3") do set arguments=!arguments! %%b
shift /3
)
echo !arguments!
问题是 arguments
在执行此循环后等于 1 1 1
而不是 1 test2 true
。
我相信内部循环已预先填充 %~3
并设置为 foo=1
并忽略了 shift 命令。我无法更改 shift
,因为我需要支持 9 个以上的参数,也无法删除外部循环(出于其他原因)。
问题是 - 我可以延迟扩展脚本参数吗?
你的问题是,%x
参数甚至在 for
循环执行之前被解析器替换为它们的初始值,所以 shift
在 for
循环中没有(立即)效果。
一个简单的解决方法:将参数 3....n 分配给一个变量并处理:
setlocal enabledelayedexpansion
for /f "usebackq tokens=2,*" %%i in ('%*') do (
for %%k in (%%j) do (
for /f "tokens=2 delims==" %%a in ("%%~k") do (
set "args=!args! %%~a"
)
)
)
set args
第一个 for
得到参数 3...
第二个 for
处理您剩余的每个参数
第三个 for
从每个 var=value
字符串中获取值。
@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
rem this is actually fetched elsewhere in live app
set procedure_arguments_count=3
set arguments=
for /L %%L in (1,1,!procedure_arguments_count!) do (
call set "aux=%%~3"
for /f "tokens=1,2 delims==" %%a in ("!aux!") do set arguments=!arguments! %%b
shift /3
)
echo !arguments!
或没有外部 FOR /L
循环
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "procedure_arguments_count=3"
set "arguments="
set "ii=%procedure_arguments_count%"
:loopfor
if [%3]==[] goto :done
if %ii% EQU 0 goto :done
for /f "tokens=1,2 delims==" %%a in ("%~3") do set arguments=%arguments% %%b
SHIFT /3
set /A ii-=1
goto :loopfor
:done
echo(%arguments%