我需要我的bat文件接受多个可选的命名参数.
mycmd.bat man1 man2 -username alice -otheroption
Run Code Online (Sandbox Code Playgroud)
例如,我的命令有2个必需参数,以及两个参数值为alice的可选参数(-username)和-otheroption:
我希望能够将这些值插入变量中.
只是给那些已经解决了这个问题的人打电话.男人这些蝙蝠文件很痛苦.
ewa*_*all 103
虽然我倾向于同意@AlekDavis的评论,但在NT shell中仍有几种方法可以做到这一点.
我将利用SHIFT命令和IF条件分支的方法,这样的......
@ECHO OFF
SET man1=%1
SET man2=%2
SHIFT & SHIFT
:loop
IF NOT "%1"=="" (
IF "%1"=="-username" (
SET user=%2
SHIFT
)
IF "%1"=="-otheroption" (
SET other=%2
SHIFT
)
SHIFT
GOTO :loop
)
ECHO Man1 = %man1%
ECHO Man2 = %man2%
ECHO Username = %user%
ECHO Other option = %other%
REM ...do stuff here...
:theend
Run Code Online (Sandbox Code Playgroud)
dbe*_*ham 63
选定的答案有效,但可以使用一些改进.
我的解决方案依赖于创建一个OPTIONS变量,该变量定义了所有选项及其默认值.OPTIONS还用于测试提供的选项是否有效.只需将选项值存储在与选项相同的变量中,即可节省大量代码.无论定义了多少个选项,代码量都是常量; 只有OPTIONS定义必须改变.
编辑 - 此外,如果强制位置参数的数量发生变化,则:循环代码必须更改.例如,通常所有参数都被命名,在这种情况下,您要解析从位置1开始而不是3开始的参数.因此,在:循环中,所有3都变为1,而4变为2.
@echo off
setlocal enableDelayedExpansion
:: Define the option names along with default values, using a <space>
:: delimiter between options. I'm using some generic option names, but
:: normally each option would have a meaningful name.
::
:: Each option has the format -name:[default]
::
:: The option names are NOT case sensitive.
::
:: Options that have a default value expect the subsequent command line
:: argument to contain the value. If the option is not provided then the
:: option is set to the default. If the default contains spaces, contains
:: special characters, or starts with a colon, then it should be enclosed
:: within double quotes. The default can be undefined by specifying the
:: default as empty quotes "".
:: NOTE - defaults cannot contain * or ? with this solution.
::
:: Options that are specified without any default value are simply flags
:: that are either defined or undefined. All flags start out undefined by
:: default and become defined if the option is supplied.
::
:: The order of the definitions is not important.
::
set "options=-username:/ -option2:"" -option3:"three word default" -flag1: -flag2:"
:: Set the default option values
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"
:loop
:: Validate and store the options, one at a time, using a loop.
:: Options start at arg 3 in this example. Each SHIFT is done starting at
:: the first option so required args are preserved.
::
if not "%~3"=="" (
set "test=!options:*%~3:=! "
if "!test!"=="!options! " (
rem No substitution was made so this is an invalid option.
rem Error handling goes here.
rem I will simply echo an error message.
echo Error: Invalid option %~3
) else if "!test:~0,1!"==" " (
rem Set the flag option using the option name.
rem The value doesn't matter, it just needs to be defined.
set "%~3=1"
) else (
rem Set the option value using the option as the name.
rem and the next arg as the value
set "%~3=%~4"
shift /3
)
shift /3
goto :loop
)
:: Now all supplied options are stored in variables whose names are the
:: option names. Missing options have the default value, or are undefined if
:: there is no default.
:: The required args are still available in %1 and %2 (and %0 is also preserved)
:: For this example I will simply echo all the option values,
:: assuming any variable starting with - is an option.
::
set -
:: To get the value of a single parameter, just remember to include the `-`
echo The value of -username is: !-username!
Run Code Online (Sandbox Code Playgroud)
真的没有那么多代码.上面的大部分代码都是评论.这是完全相同的代码,没有注释.
@echo off
setlocal enableDelayedExpansion
set "options=-username:/ -option2:"" -option3:"three word default" -flag1: -flag2:"
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"
:loop
if not "%~3"=="" (
set "test=!options:*%~3:=! "
if "!test!"=="!options! " (
echo Error: Invalid option %~3
) else if "!test:~0,1!"==" " (
set "%~3=1"
) else (
set "%~3=%~4"
shift /3
)
shift /3
goto :loop
)
set -
:: To get the value of a single parameter, just remember to include the `-`
echo The value of -username is: !-username!
Run Code Online (Sandbox Code Playgroud)
此解决方案在Windows批处理中提供Unix样式参数.这不是Windows的标准 - 批处理通常具有所需参数之前的选项,并且选项以前缀为前缀/.
此解决方案中使用的技术很容易适应Windows风格的选项.
%1,并一直持续到arg 1不以//.SET /VAR=VALUE失败了SET "/VAR=VALUE".无论如何,我已经在我的解决方案中这样做了./.通过使用隐式定义的//选项作为退出选项解析循环的信号,可以消除此限制.//"选项" 不会存储任何内容.
更新2015-12-28:支持!选项值
在上面的代码中,每个参数都被扩展,同时启用了延迟扩展,这意味着!最有可能被剥离,或者!var!扩展了类似的东西.另外,^如果!存在也可以剥离.对未注释的代码的以下小修改消除了限制,!以及^保留在选项值中.
@echo off
setlocal enableDelayedExpansion
set "options=-username:/ -option2:"" -option3:"three word default" -flag1: -flag2:"
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B"
:loop
if not "%~3"=="" (
set "test=!options:*%~3:=! "
if "!test!"=="!options! " (
echo Error: Invalid option %~3
) else if "!test:~0,1!"==" " (
set "%~3=1"
) else (
setlocal disableDelayedExpansion
set "val=%~4"
call :escapeVal
setlocal enableDelayedExpansion
for /f delims^=^ eol^= %%A in ("!val!") do endlocal&endlocal&set "%~3=%%A" !
shift /3
)
shift /3
goto :loop
)
goto :endArgs
:escapeVal
set "val=%val:^=^^%"
set "val=%val:!=^!%"
exit /b
:endArgs
set -
:: To get the value of a single parameter, just remember to include the `-`
echo The value of -username is: !-username!
Run Code Online (Sandbox Code Playgroud)
cha*_*ott 17
如果你想使用可选参数,而不是命名参数,那么这种方法对我有用.我认为这是更容易遵循的代码.
REM Get argument values. If not specified, use default values.
IF "%1"=="" ( SET "DatabaseServer=localhost" ) ELSE ( SET "DatabaseServer=%1" )
IF "%2"=="" ( SET "DatabaseName=MyDatabase" ) ELSE ( SET "DatabaseName=%2" )
REM Do work
ECHO Database Server = %DatabaseServer%
ECHO Database Name = %DatabaseName%
Run Code Online (Sandbox Code Playgroud)
优点
%1, %2, ...%*完好无损/arg两种-arg风格缺点
setlocal本地作用域或编写随附的:CLEAR-ARGS例程!--force喜欢-f)""参数支持以下是以下参数如何与 .bat 变量相关的示例:
>> testargs.bat /b 3 -c /d /e /f /g /h /i /j /k /bar 5 /foo "c:\"
echo %* | /b 3 -c /d /e /f /g /h /i /j /k /bar 5 /foo "c:\"
echo %ARG_FOO% | c:\
echo %ARG_A% |
echo %ARG_B% | 3
echo %ARG_C% | 1
echo %ARG_D% | 1
Run Code Online (Sandbox Code Playgroud)
@echo off
setlocal
CALL :ARG-PARSER %*
::Print examples
echo: ALL: %*
echo: FOO: %ARG_FOO%
echo: A: %ARG_A%
echo: B: %ARG_B%
echo: C: %ARG_C%
echo: D: %ARG_D%
::*********************************************************
:: Parse commandline arguments into sane variables
:: See the following scenario as usage example:
:: >> thisfile.bat /a /b "c:\" /c /foo 5
:: >> CALL :ARG-PARSER %*
:: ARG_a=1
:: ARG_b=c:\
:: ARG_c=1
:: ARG_foo=5
::*********************************************************
:ARG-PARSER
::Loop until two consecutive empty args
:loopargs
IF "%~1%~2" EQU "" GOTO :EOF
set "arg1=%~1"
set "arg2=%~2"
shift
::Allow either / or -
set "tst1=%arg1:-=/%"
if "%arg1%" NEQ "" (
set "tst1=%tst1:~0,1%"
) ELSE (
set "tst1="
)
set "tst2=%arg2:-=/%"
if "%arg2%" NEQ "" (
set "tst2=%tst2:~0,1%"
) ELSE (
set "tst2="
)
::Capture assignments (eg. /foo bar)
IF "%tst1%" EQU "/" IF "%tst2%" NEQ "/" IF "%tst2%" NEQ "" (
set "ARG_%arg1:~1%=%arg2%"
GOTO loopargs
)
::Capture flags (eg. /foo)
IF "%tst1%" EQU "/" (
set "ARG_%arg1:~1%=1"
GOTO loopargs
)
goto loopargs
GOTO :EOF
Run Code Online (Sandbox Code Playgroud)