给定一个可选的端口参数,端口号的长度可以变化,如何从批处理脚本的命令行参数中获取端口号?
示例:
foo.bat --foo bar --port 80 --bar foo
应输出:
80
我到目前为止,试图使用子串。
set CMD_LINE_ARGS=%*
@rem Remove all chars and port arg
set PORT_ARG_REMOVED=%CMD_LINE_ARGS:*-port =%
@rem Obviously, this is where I fail to remove trailing chars
set PORT_NUM=%PORT_ARG_REMOVED: *=%
echo %PORT_NUM%
修改
我选择的答案是因为它符合我特定的用例,其中所有参数都被传递给我正在包装的命令。而且,我只需要特定可选参数的值。不需要循环。
这里有一些非常好的答案可以解决一般的可选参数解析问题。所以,随时向所有人投票。
答案 0 :(得分:3)
看到你真的希望看到子字符串工作',这里的脚本按照你的意图进行结构化和编码。
@Set "CMD_LINE_ARGS=%*"
@Rem Remove all chars and port arg
@Set "PORT_ARG_REMOVED=%CMD_LINE_ARGS:*-port =%"
@Rem Remove trailing chars
@Set "PORT_NUM=%PORT_ARG_REMOVED: ="&:"%"
@Echo %PORT_NUM%
@Pause
答案 1 :(得分:2)
您可以将%1
,%2
等用于单独的命令行参数。在您的情况下,--port
将为%3
,其值为%4
。
幸运的是,还有shift
命令,它将所有参数转换为2变为1,3变为2等。
这意味着你可以“刮掉”'循环中的所有命令行参数。您继续转移,当您遇到--port
时,您知道下一个将成为端口号,您可以将其存储在适当的变量中(使用set
)供以后使用。
如果你这样实现它,你可以实现一堆可选参数,顺序也不重要。
所以在代码中,你的' foo.bat'可能看起来像这样:
@echo off
:: No parameters given? Then run ourselves with the defaults from the question.
if "%1"=="" goto none
:: Actual reading of parameters starts here.
:loop
if "%1"=="--port" set port=%2
:: Of course you need the other ifs only if you're interested in these parameters
if "%1"=="--foo" set foo=%2
if "%1"=="--bar" set bar=%2
:: Shift all parameters, except %0. Do it twice to skip the parameter and its value.
shift /1
shift /1
:: As long as there are more, keep looping. You can even parse more than 10 parameters this way!
if not "%1"=="" goto loop
:: Output what we've found
echo The specified port is %port%
echo Foo is set to %foo%
echo The bar is at %bar%
pause
exit /b
:: If no parameters are given, call ourselves with example parameters.
:none
call %0 --foo bar --port 80 --bar foo
没有只显示端口号的演示垃圾的打印版本。我认为这是您当前代码的替代品。
@echo off
:loop
if "%1"=="--port" set port=%2
shift /1
shift /1
if not "%1"=="" goto loop
echo %port%
答案 2 :(得分:2)
一个更简单明了的方法来获取所有参数无关紧要:
@echo off
setlocal EnableDelayedExpansion
set "arg="
for %%a in (%*) do (
if not defined arg (
set "arg=%%a"
) else (
set "!arg:~2!=%%a"
set "arg="
)
)
echo foo = %foo%
echo port = %port%
echo bar = %bar%
如果您喜欢短代码,下面的版本会在较少的行中执行相同的任务:
@echo off
set "args= %*"
set "args=%args: --=+%"
set "args=%args: ==%"
set args=%args:+=&set %
echo foo = %foo%
echo port = %port%
echo bar = %bar%
如果您想查看较短版本的工作原理,只需删除@echo off
行并执行即可。
答案 3 :(得分:0)
我会先使用sub-string replacement删除--port
部分,然后按for /F
loop获取值,如下所示:
set CMD_LINE_ARGS=%*
@rem Remove everything up to `--port` + a space:
set "PORT_ARG_REMOVED=%CMD_LINE_ARGS:*--port =%"
@rem Extract first space- (or tab-)separated item:
for /F "tokens=1" %%A in ("%PORT_ARG_REMOVED%") do set "PORT_NUM=%%A"
echo/%PORT_NUM%
for /F
方法具有很大的优势,即当提供多个连续的 SPACE 来分离命令行参数时,它甚至可以正常工作。
如果您希望代码允许所有标准标记分隔符( SPACE , TAB ,,
,;
,{{1并且代码为=
的字符而不仅仅是 SPACE ,您可以将代码更改为:
0xFF
实际上我更喜欢这种方式,因为不涉及字符串操作,因为参数列表是以set "FLAG="
@rem Use a standard `for` loop to walk through the arguments:
for %%A in (%*) do (
@rem Capture the argument following the `--port` item:
if defined FLAG if not defined PORT_NUM set "PORT_NUM=%%~A"
@rem Use a `FLAG` variable to delay capturing argument by an iteration;
@rem to match `--port` case-sensitively, remove the `/I` option:
if /I "%%~A"=="--port" set "FLAG=#"
)
echo/%PORT_NUM%
的性质解析的。