Wybrana odpowiedź działa, ale może to wykorzystać pewną poprawę.
- Prawdopodobnie opcje powinny zostać zainicjalizowane na wartości domyślne.
- Byłoby miło zachować% 0, a także wymagane argumenty% 1 i% 2.
- Staje się bólem mieć blok IF dla każdej opcji, zwłaszcza, że liczba opcji rośnie.
- Byłoby miło mieć prosty i zwięzły sposób szybkiego zdefiniowania wszystkich opcji i ustawień domyślnych w jednym miejscu.
- Byłoby dobrze wspierać autonomiczne opcje, które służą jako flagi (brak wartości po opcji).
- Nie wiemy, czy argument jest zawarty w ofertach. Nie wiemy również, czy wartość arg została przekazana przy użyciu znaków zbiegów. Lepiej uzyskać dostęp do argumentu za pomocą% ~ 1 i zamknąć zadanie w cudzysłowie. Następnie partia może polegać na braku cytatów, ale znaki specjalne są zazwyczaj bezpieczne bez ucieczki. (Nie jest to punktor kuloodporny, ale obsługuje większość sytuacji)
Moje rozwiązanie polega na utworzeniu zmiennej OPTIONS, która definiuje wszystkie opcje i ich ustawienia domyślne. OPTIONS służy również do sprawdzenia, czy podana opcja jest poprawna. Ogromna ilość kodu jest zapisywana po prostu poprzez przechowywanie wartości opcji w zmiennych o tej samej nazwie co opcja. Ilość kodu jest stała bez względu na liczbę zdefiniowanych opcji; tylko definicja OPCJE musi się zmienić.
EDIT- Również: Kod pętla musi się zmienić, jeśli liczba obowiązkowych pozycyjnych argumentów zmian. Na przykład, często razy wszystkie argumenty są nazwane, w którym to przypadku chcesz przeanalizować argumenty zaczynają w pozycji 1 zamiast 3. Dlatego w: pętli, wszystkie 3 stają się 1 i 4 staje 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!
Naprawdę nie ma zbyt wiele kodu. Większość powyższego kodu to komentarze. Oto dokładnie ten sam kod, bez komentarzy.
@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!
To rozwiązanie zapewnia Unix argumenty w stylu partii Windows. Nie jest to normą dla systemu Windows - partia ma zwykle opcje poprzedzające wymagane argumenty, a opcje są poprzedzone prefiksem /
.
Techniki stosowane w tym rozwiązaniu można łatwo dostosować do opcji stylu systemu Windows.
- Pętla parsowanie zawsze szuka opcji na
%1
, a to trwa aż arg 1 nie rozpoczyna się /
- Uwaga, które wyznaczają zadania musi być ujęty w cudzysłów, jeśli nazwa zaczyna się
/
.
zawiedzie
SET "/VAR=VALUE"
działa. W każdym razie robię to już w moim rozwiązaniu.
- Standardowy styl Windows wyklucza możliwość pierwszej wymaganej wartości argumentu rozpoczynającej się od
/
. Ograniczenie to można wyeliminować, wykorzystując niejawnie zdefiniowaną opcję //
, która służy jako sygnał do wyjścia z pętli analizowania opcji. Nic nie będzie przechowywane dla "opcji" //
.
Aktualizacja 28.12.2015: Wsparcie !
w opcji wartości
W powyższym kodzie, każdy argument jest rozszerzany podczas opóźniony rozbudowa jest włączona, co oznacza, że !
są najprawdopodobniej usunięte, albo coś takiego jak !var!
jest rozszerzone. Ponadto, ^
można również usunąć, jeśli występuje !
. Następująca niewielka modyfikacja niezredagowanego kodu usuwa ograniczenie tak, że !
i ^
są zachowane w wartościach opcji.
@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!
Ta strona jest obiecujący: http://www.pcguide.com/vb/showthread.php?t=52323 –
Każdy powód dlaczego trzeba to zrobić w pliku BAT i nie mówią w języku VBScript? Być może istnieje sposób, aby to zrobić w pliku BAT, ale pozostając przy podejściu do pliku BAT, "wkraczasz w świat bólu, synu". :-) –
Jeszcze lepiej jest używać PowerShell. Ma bardzo zaawansowane i wbudowane zarządzanie parametrami. –