如何在Windows批处理脚本中获取可选的命令行参数值作为字符串?

时间:2018-03-28 20:52:03

标签: windows batch-file

给定一个可选的端口参数,端口号的长度可以变化,如何从批处理脚本的命令行参数中获取端口号?

示例:

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%

修改

我选择的答案是因为它符合我特定的用例,其中所有参数都被传递给我正在包装的命令。而且,我只需要特定可选参数的值。不需要循环。

这里有一些非常好的答案可以解决一般的可选参数解析问题。所以,随时向所有人投票。

4 个答案:

答案 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% 的性质解析的。