Вдохновленный ответом в другом месте от @Jon, я создал более общий алгоритм для извлечения именованных параметров, необязательных значений и переключателей.
Допустим, мы хотим реализовать утилиту foobar
. Требуется начальная команда. Он имеет необязательный параметр --foo
, который принимает необязательное значение (которое, конечно, не может быть другим параметром); если значение отсутствует, по умолчанию используется значение default
. Он также имеет необязательный параметр --bar
, который принимает обязательное значение. Наконец, он может принимать флаг --baz
без допустимого значения. Ох, и эти параметры могут быть в любом порядке.
Другими словами, это выглядит так:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
Вот решение:
@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson
SET CMD=%~1
IF "%CMD%" == "" (
GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=
SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
SHIFT
IF NOT "%ARG%" == "" (
IF NOT "%ARG:~0,2%" == "--" (
SET FOO=%ARG%
SHIFT
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE IF "%PARAM%" == "--bar" (
SHIFT
IF NOT "%ARG%" == "" (
SET BAR=%ARG%
SHIFT
) ELSE (
ECHO Missing bar value. 1>&2
ECHO:
GOTO usage
)
) ELSE IF "%PARAM%" == "--baz" (
SHIFT
SET BAZ=true
) ELSE IF "%PARAM%" == "" (
GOTO endargs
) ELSE (
ECHO Unrecognized option %1. 1>&2
ECHO:
GOTO usage
)
GOTO args
:endargs
ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
ECHO Baz
)
REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof
:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1
- Используйте
SETLOCAL
, чтобы переменные не попадали в вызывающую среду.
- Не забудьте инициализировать переменные
SET FOO=
и т. Д., Если кто-то определил их в вызывающей среде.
- Используйте
%~1
для удаления кавычек.
- Используйте
IF "%ARG%" == ""
, а не IF [%ARG%] == []
, потому что [
и ]
вообще не воспроизводятся, если значения заканчиваются пробелом.
- Даже если вы
SHIFT
внутри блока IF
, текущие аргументы, такие как %~1
, не обновляются, поскольку они определяются при разборе IF
. Вы можете использовать %~1
и %~2
внутри блока IF
, но это может сбить с толку, потому что у вас есть SHIFT
. Вы можете поставить SHIFT
в конце блока для ясности, но это может потеряться и / или сбить людей с толку. Так что «захват» %~1
и %~1
вне блока кажется лучшим.
- Вы не хотите использовать параметр вместо необязательного значения другого параметра, поэтому вам нужно проверить
IF NOT "%ARG:~0,2%" == "--"
.
- Будьте осторожны только с
SHIFT
, когда вы используете один из параметров.
- Дублированный код
SET FOO=%DEFAULT_FOO%
вызывает сожаление, но альтернативой может быть добавление IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
вне блока IF NOT "%ARG%" == ""
. Однако, поскольку он все еще находится внутри блока IF "%PARAM%" == "--foo"
, значение %FOO%
было бы оценено и установлено до того, как вы в него войдете, поэтому вы никогда не обнаружите, что в оба присутствовал параметр --foo
. , а также , что значение %FOO%
отсутствовало.
- Обратите внимание, что
ECHO Missing bar value. 1>&2
отправляет сообщение об ошибке в stderr.
- Хотите пустую строку в командном файле Windows? Вы должны использовать
ECHO:
или один из вариантов.