Seçilen cevap işe yarıyor, ancak biraz iyileştirme yapabilir.
- Seçenekler muhtemelen varsayılan değerlerle başlatılmalıdır.
- % 0 ve gerekli bağımsız değişkenler% 1 ve% 2'yi korumak güzel olurdu.
- Her seçenek için bir IF bloğuna sahip olmak, özellikle seçeneklerin sayısı arttıkça bir acı haline geliyor.
- Tüm seçenekleri ve varsayılanları tek bir yerde hızlı bir şekilde tanımlamanın basit ve öz bir yoluna sahip olmak güzel olurdu.
- Bayrak görevi gören bağımsız seçenekleri desteklemek iyi olur (seçeneğin ardından değer yoktur).
- Bir argümanın tırnak içinde olup olmadığını bilmiyoruz. Kaçış karakterleri kullanılarak bir arg değerinin geçip geçmediğini de bilmiyoruz. % ~ 1 kullanarak bir argümana erişmek ve atamayı tırnak içine almak daha iyidir. Daha sonra grup, tırnak işaretlerinin olmamasına güvenebilir, ancak özel karakterler hala kaçmadan genellikle güvenlidir. (Bu, kurşun geçirmez değildir, ancak çoğu durumu idare eder)
Çözümüm, tüm seçenekleri ve varsayılanlarını tanımlayan bir OPTIONS değişkeninin oluşturulmasına dayanıyor. OPTIONS, sağlanan bir seçeneğin geçerli olup olmadığını test etmek için de kullanılır. Olağanüstü miktarda kod, seçenek değerlerinin seçenekle aynı adı verilen değişkenlerde saklanmasıyla kaydedilir. Kod miktarı, kaç seçeneğin tanımlandığına bakılmaksızın sabittir; yalnızca SEÇENEKLER tanımının değiştirilmesi gerekir.
DÜZENLE - Ayrıca, zorunlu konum bağımsız değişkenlerinin sayısı değişirse: döngü kodu da değişmelidir. Örneğin, çoğu zaman tüm bağımsız değişkenler adlandırılır, bu durumda bağımsız değişkenleri 3 yerine 1. konumda ayrıştırmak istersiniz. Yani: döngüsü içinde 3'ün tamamı 1 olur ve 4, 2 olur.
@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!
Gerçekten o kadar çok kod yok. Yukarıdaki kodun çoğu yorumlardır. İşte yorumlar olmadan aynı kod.
@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!
Bu çözüm, bir Windows grubu içinde Unix stili argümanlar sağlar. Bu, Windows için bir norm değildir - toplu iş, genellikle gerekli bağımsız değişkenlerin önünde seçeneklere sahiptir ve seçeneklerin önünde bulunur /
.
Bu çözümde kullanılan teknikler, Windows tarzı seçenekler için kolayca uyarlanabilir.
- Ayrıştırma döngüsü her zaman için bir seçenek arar
%1
ve arg 1 ile başlamayana kadar devam eder./
- İsim ile başlıyorsa SET atamalarının tırnak içine alınması gerektiğini unutmayın
/
.
SET /VAR=VALUE
başarısız olur
SET "/VAR=VALUE"
. Bunu zaten çözümümde yapıyorum.
- Standart Windows stili, ile başlayan ilk gerekli argüman değerinin olasılığını ortadan kaldırır
/
. Bu sınırlama //
, seçenek ayrıştırma döngüsünden çıkmak için bir sinyal görevi gören örtük olarak tanımlanmış bir seçenek kullanılarak ortadan kaldırılabilir . //
"Seçenek" için hiçbir şey depolanmaz .
2015-12-28 Güncellemesi: Destek!
Seçenek değerleri
Yukarıdaki kodda, her bağımsız değişken, gecikmeli genişleme etkinleştirilirken genişletilir, bu !
da büyük olasılıkla kaldırıldığı veya benzer bir !var!
şeyin genişletildiği anlamına gelir . Ayrıca ^
varsa sıyrılabilir !
. Yorumsuz kodda yapılan aşağıdaki küçük değişiklik , seçenek değerlerinde korunan !
ve bu sınırlamayı ortadan kaldırır ^
.
@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!