선택한 답변이 작동하지만 약간의 개선이 필요할 수 있습니다.
- 옵션은 아마도 기본값으로 초기화되어야합니다.
- % 0과 필수 인수 % 1 및 % 2를 보존하는 것이 좋습니다.
- 특히 옵션 수가 증가함에 따라 모든 옵션에 대해 IF 블록을 사용하는 것은 고통스러워집니다.
- 모든 옵션과 기본값을 한곳에서 신속하게 정의 할 수있는 간단하고 간결한 방법이 있으면 좋을 것입니다.
- 플래그 역할을하는 독립형 옵션을 지원하는 것이 좋습니다 (옵션 다음에 값 없음).
- 인수가 따옴표로 묶여 있는지 알 수 없습니다. 이스케이프 문자를 사용하여 인수 값이 전달되었는지도 알 수 없습니다. % ~ 1을 사용하여 인수에 액세스하고 할당을 따옴표로 묶는 것이 좋습니다. 그런 다음 일괄 처리는 따옴표를 묶지 않는 것에 의존 할 수 있지만 특수 문자는 일반적으로 이스케이프 없이도 안전합니다. (이것은 방탄이 아니지만 대부분의 상황을 처리합니다)
내 솔루션은 모든 옵션과 기본값을 정의하는 OPTIONS 변수의 생성에 의존합니다. OPTIONS는 제공된 옵션이 유효한지 테스트하는데도 사용됩니다. 옵션과 동일한 이름의 변수에 옵션 값을 저장하기 만하면 엄청난 양의 코드가 절약됩니다. 코드의 양은 정의 된 옵션 수에 관계없이 일정합니다. OPTIONS 정의 만 변경하면됩니다.
편집 -또한 필수 위치 인수의 수가 변경되면 : loop 코드도 변경되어야합니다. 예를 들어, 종종 모든 인수의 이름이 지정됩니다.이 경우 3이 아닌 위치 1에서 시작하는 인수를 구문 분석하려고합니다. 따라서 : loop 내에서 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!
정말 많은 코드가 없습니다. 위 코드의 대부분은 주석입니다. 다음은 주석이없는 똑같은 코드입니다.
@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!
이 솔루션은 Windows 배치 내에서 Unix 스타일 인수를 제공합니다. 이것은 Windows의 표준이 아닙니다. 일반적으로 필요한 인수 앞에 옵션이 있고 옵션 앞에 /
.
이 솔루션에 사용 된 기술은 Windows 스타일의 옵션에 쉽게 적용됩니다.
- 구문 분석 루프는 항상에서 옵션을 찾고
%1
arg 1이 다음으로 시작하지 않을 때까지 계속됩니다./
- 이름이로 시작하는 경우 SET 할당 은 따옴표로 묶어야합니다
/
. 작동
SET /VAR=VALUE
하지 않습니다
SET "/VAR=VALUE"
. 어쨌든 내 솔루션에서 이미 이것을하고 있습니다.
- 표준 Windows 스타일은로 시작하는 첫 번째 필수 인수 값의 가능성을 배제합니다
/
. 이 제한은 //
옵션 구문 분석 루프를 종료하는 신호 역할 을하는 암시 적으로 정의 된 옵션을 사용하여 제거 할 수 있습니다 . //
"옵션" 에 대해서는 아무것도 저장되지 않습니다 .
2015-12-28 업데이트 :!
in 옵션 값 지원
위의 코드에서 각 인수는 확장되고 지연된 확장이 활성화되어 있습니다. 즉, !
대부분 제거되거나 다른 항목 !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!