Выбранный ответ работает, но он может использовать некоторые улучшения.
- Возможно, параметры должны быть инициализированы значениями по умолчанию.
- Было бы неплохо также сохранить% 0как требуемые аргументы% 1 и% 2.
- Больно иметь блок IF для каждого параметра, особенно по мере роста количества вариантов.
- Было бы неплохо иметьпростой и краткий способ быстрого определения всех параметров и значений по умолчанию в одном месте.
- Было бы хорошо поддерживать автономные параметры, которые служат в качестве флагов (без значения после параметра).
- Мыне знаю, если арг заключен в кавычки.Мы также не знаем, было ли передано значение arg с использованием экранированных символов.Лучше получить доступ к аргументу с помощью% ~ 1 и заключить назначение в кавычки.Тогда пакет может полагаться на отсутствие заключающих в кавычки, но специальные символы все еще, как правило, безопасны без экранирования.(Это не пуленепробиваемое, но оно обрабатывает большинство ситуаций)
Мое решение основано на создании переменной 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!
Там действительно не так много кода.Большая часть кода выше - это комментарии.Вот точно такой же код, без комментариев.
@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!
Это решение предоставляет аргументы стиля Unix в пакете Windows.Это не является нормой для Windows - в пакете обычно есть параметры, предшествующие обязательным аргументам, и к параметрам добавляется префикс /
.
Методы, используемые в этом решении, легко адаптируются к параметрам в стиле Windows.
- Цикл синтаксического анализа всегда ищет параметр в
%1
и продолжается до тех пор, пока аргумент 1 не начинается с /
- Обратите внимание, что назначения SET должен быть заключен в кавычки, если имя начинается с
/
.
SET /VAR=VALUE
не работает
SET "/VAR=VALUE"
работает.В любом случае я уже делаю это в своем решении. - Стандартный стиль Windows исключает возможность первого значения обязательного аргумента, начинающегося с
/
.Это ограничение может быть устранено путем использования неявно определенной опции //
, которая служит сигналом для выхода из цикла синтаксического анализа опции.Ничего не будет сохранено для //
«опции».
Обновление 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!